【Flask从入门到精通:第八课:ORM、Flask-SQLAlchemy】

ORM

ORM 全拼Object-Relation Mapping,中文意为 对象-关系映射。主要实现模型对象到关系数据库数据的映射。

ORM提供了一种面向对象操作数据库的方式给开发者。不需要编写原生SQL语句也能操作数据库,实现了业务代码与底层数据的解耦。

优点:

  • 只需要面向对象编程, 不需要面向数据库编写SQL.
    • 对数据库的操作都转化成对类/对象的属性和方法的操作. 表字段—>对象属性, SQL关键字-> 操作方法
    • 不用编写各种数据库的原生sql语句,当然,也可以编写原生SQL语句。
  • 实现了数据模型代码与数据库数据的解耦, 屏蔽了不同数据库操作上的差异
    • 不再需要关注当前项目使用的是哪种数据库。
    • 通过简单的配置就可以轻松更换数据库, 而不需要修改业务代码.

缺点:

  • 相比较直接使用SQL语句操作数据库,ORM需要把操作转换成SQL语句,所以有性能损失.
  • 根据对象的操作转换成SQL语句,根据查询的结果转化成模型实例对象, 在映射过程中有性能损失.
  • 不同的ORM提供的操作不一样,增加了学习成本

Flask-SQLAlchemy

flask默认提供模型操作,但是并没有提供ORM,所以一般开发的时候我们会采用flask-SQLAlchemy模块来实现ORM操作。

SQLAlchemy是一个python语言编写的高性能的关系型数据库ORM框架,它提供了高层的 ORM 和底层的原生数据库的操作。

我们使用sqlalchemy 不需要调用sqlalchemy 本身这个模块,而是采用flask-sqlalchemy ,这是一个简化了 SQLAlchemy 操作的flask扩展模块。(主要是简化了sqlalchemy初始化代码和分页操作等)

SQLAlchemy:https://docs.sqlalchemy.org/en/14/

中文文档:https://www.osgeo.cn/sqlalchemy/orm/index.html

flask-SQLAlchemy:https://flask-sqlalchemy.palletsprojects.com/en/2.x/quickstart/

安装 flask-sqlalchemy【清华源】

pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple

如果sqlalchemy连接的是 mysql /MariaDB数据库,需要安装 mysqldb 或pymysql驱动

conda install flask-mysqldb -c conda-forge

安装flask-mysqldb时,注意

使用pip install 安装 flask-mysqldb的时候,python底层依赖于一个底层的模块 mysqlclient 模块
如果没有这个模块,则会报错如下:Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-21hysnd4/mysqlclient/

解决方案:

sudo apt-get install -y libmysqlclient-dev python3-dev# 运行上面的安装命令如果再次报错如下:
#   dpkg 被中断,您必须手工运行 ‘sudo dpkg --configure -a’ 解决此问题。# 则根据提示执行命令以下命令,再次安装mysqlclient
#    sudo dpkg --configure -a
#    apt-get install libmysqlclient-dev python3-dev解决了mysqlclient问题以后,重新安装 flask-mysqldb即可。
pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple

原生SQLAlchemy连接配置操作

db.py,代码:

from sqlalchemy import create_engine   # 驱动引擎
from sqlalchemy.ext.declarative import declarative_base # 数据库基类
from sqlalchemy import Column, Integer, String, Boolean, Numeric, Text # 字段、整型
from sqlalchemy.orm import sessionmaker  # 连接会话engine = create_engine(# 连接数据库的URL# url="mysql+pymysql://root:123@127.0.0.1:3306/students?charset=utf8mb4",  # 如果底层驱动是pymysqlurl="mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4",    # 如果底层驱动是MysqlDBecho=True, # 当设置为True时会将orm语句转化为sql语句打印,一般debug的时候可用pool_size=8, # 连接池的大小,默认为5个,设置为0时表示连接无限制pool_recycle=60*30 # 设置时间以限制数据库多久没连接自动断开
)DbSession = sessionmaker(bind=engine)
session = DbSession()# 创建数据基类
Model = declarative_base()

manage.py,代码:

import db
class Student(db.Model):__tablename__ = "tb_student"id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(255))sex  = db.Column(db.Boolean)age  = db.Column(db.Integer)class_name = db.Column("class", db.String(255),)description = db.Column(db.Text)is_delete = db.Column(db.Boolean, nullable=True, default=False)if __name__ == '__main__':# 如果没有提前声明模型中的数据表,则可以采用以下代码生成数据表,# 如果数据库中已经声明了有数据表,则不会继续生成db.Model.metadata.create_all(db.engine)# 根据ID查询一条数据# ret = db.session.query(Student).get(19)# print(ret)# print(ret.name)# print(ret.class_name)## # 查询所有数据# data_list = db.session.query(Student).all()# print(data_list)# for data in data_list:#     print(data.name)# # 按条件查询# data_list = db.session.query(Student).filter(Student.sex==True, Student.class_name=='301').all()# print(data_list)# for data in data_list:#     print(data.sex, data.name)# 添加一条数据# student = Student(#     name="xiaohua",#     class_name="305",#     sex=False,#     age=18,#     description="美美的..",# )# db.session.add(student)# db.session.commit()## # 添加多条数据# student_list = [#     Student(name="xiaohei", class_name="305", sex=False, age=18, description="美美的..",),#     Student(name="xiaobai", class_name="304", sex=True, age=18, description="美美的..",),#     Student(name="xiaohui", class_name="303", sex=False, age=18, description="美美的..",),# ]## db.session.add_all(student_list)# db.session.commit()# 更新一条数据# student = db.session.query(Student).get(35)# student.name = "小会"# db.session.commit()# 更新多条数据# db.session.query(Student).filter(Student.class_name=="303").update({Student.age:Student.age+1})# db.session.commit()# 删除一条数据# student = db.session.query(Student).get(35)# db.session.delete(student)# db.session.commit()# 删除多条数据db.session.query(Student).filter(Student.class_name == "401").delete()# 原生SQL语句# 读cursor = db.session.execute('select * from tb_student')# 一条# data = cursor.fetchone()# print(data)# 多条# data_list = cursor.fetchall()# print(data_list)# 写[添加、删除、修改]cursor = db.session.execute('insert into tb_student(name, class, age, sex, description) values(:name, :class, :age, :sex, :description)',params={"name": "xiaohong","class": "307","age": 19,"sex": 0,"description": ".....",})db.session.commit()print(cursor.lastrowid) # 获取最后添加的主键ID

数据库连接设置

  • 在 Flask-SQLAlchemy 中,数据库的链接配置信息使用URL指定,而且程序使用的数据库必须保存到Flask的 SQLALCHEMY_DATABASE_URI 配置项中

manage.py,代码:

# SQLAlchemy的链接配置:"数据库名://账户名:密码@服务器地址:端口/数据库名称?配置参数选项"
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:123@127.0.0.1:3306/flaskdemo?charset=utf8mb4"# 如果不使用mysqldb改用pymysql,则需要在连接时指定pymysql
# app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123@127.0.0.1:3306/flaskdemo?charset=utf8mb4"

其他设置项:

# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = True
#查询时会显示原始SQL语句
SQLALCHEMY_ECHO = True
  • 配置完成需要去 MySQL 中创建项目所使用的数据库
mysql -uroot -p123
create database flaskdemo charset=utf8mb4;

常用的SQLAlchemy字段类型

模型字段类型名python中数据类型说明
Integerint普通整数,一般是32位
SmallIntegerint取值范围小的整数,一般是16位
BigIntegerint不限制精度的整数
Floatfloat浮点数
Numericdecimal.Decimal普通数值,一般是32位
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长Unicode字符串
UnicodeTextunicode变长Unicode字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
DateTimedatetime.datetime日期和时间
Datedatetime.date日期
Timedatetime.time时间
LargeBinarybytes二进制文件内容
Enumenum.Enum枚举类型,相当于django的choices,但是功能没有choices那么强大

常用的SQLAlchemy列约束选项

选项名说明
primary_key如果为True,代表当前数据表的主键
unique如果为True,为这列创建唯一 索引,代表这列不允许出现重复的值
index如果为True,为这列创建普通索引,提高查询效率
nullable如果为True,允许有空值,如果为False,不允许有空值
default为这列定义默认值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/45722.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux rpm打包(rpmbuild、spec文件)(rpmlint)(Red Hat Package Manager)(rpm包制作、安装包制作)

文章目录 RPM 打包概述定义与重要性核心组件- rpm:基本命令行工具,用于安装、查询、验证和卸载RPM包。- rpmbuild:用于构建 RPM 软件包的工具。- spec 文件:定义了如何构建 RPM 包的脚本,包括包描述、版本、构建指令等…

硬件产品经理:电子产品加工成本

目录 1、板材费用 2、SMT、THT加工 3、组装费 4、测试费 电子产品的加工主体可以分为四个大的部分: 1、板材费用 首选就是PCB的板材费用,一般是按照平米计算的,普通双层板是400左右/平米。 量产会更便宜一些。 如果沉金或其他加工工艺,成本会增加不少。 2、SMT、THT加工…

Milvus 核心设计 (4) ---- metric及index原理详解与示例(2)

目录 背景 Binary Embedding 定义与特点 常见算法 应用场景 距离丈量的方式 Jaccard Hamming 代码实现 Index BIN_FLAT BIN_IVF_FLAT Sparse embeddings 定义 应用场景 优点 实现方式 距离丈量方式 IP Index SPARSE_INVERTED_INDEX 应用场景 优势 SPAR…

零信任的架构结合模块化沙箱,实现一机两用的解决方案

零信任沙箱是深信达提出的一种数据安全解决方案,它将零信任原则与SDC沙箱技术的优势相结合。零信任原则是一种安全概念,核心思想是“永不信任,总是验证”。它要求对每一个访问请求都进行严格的身份验证和授权,无论请求来源于内部还…

从RL的专业角度解惑 instruct GPT的目标函数

作为早期chatGPT背后的核心技术,instruct GPT一直被业界奉为里程碑式的著作。但是这篇论文关于RL的部分确写的非常模糊,几乎一笔带过。当我们去仔细审查它的目标函数的时候,心中不免有诸多困惑。特别是作者提到用PPO来做强化学习,…

【微信小程序知识点】手机号验证组件

手机验证组件,用于帮助开发者向用户发起手机号申请,必须经过用户同意后,才能获得由平台验证后的手机号,进而为用户提供相应的服务。 手机号验证组件分为两种:手机号快速验证组件以及手机号实时验证组件。 1.手机号快速…

【微信小程序知识点】自定义构建npm

在实际开发中,随着项目的功能越来越多,项目越来越复杂,文件目录也变得很繁琐,为了方便进行项目的开发,开发人员通常会对目录结构进行优化调整,例如:将小程序源码放到miniprogram目录下。 &…

【C++】使用gtest做单元测试框架写单元测试

本文主要介绍在将gtest框架引入到项目里过程中遇到的问题。 我的需求如下: 用CMake构建项目。我要写一些测试程序验证某些功能,但是不想每一个测试都新建一个main函数。 因为新建一个main函数就要在CMakeList.txt里增加一个project,非常不方便。 于是我搜了下,C++里有没…

Portainer工具

Portainer是一款免费、开源的Docker的图形化管理工具,其能够提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集中管理和…

深入理解JS中的闭包

闭包是JavaScript中一个非常强大的特性,它允许函数访问并操作函数外部的变量。在深入理解闭包之前,我们需要先了解JavaScript的作用域和作用域链的概念。 1、作用域和作用域链 在JavaScript中,作用域决定了代码块中变量和其他资源的可见性。…

Flink实时开发添加水印的案例分析

在Flink中,处理时间序列数据时,通常需要考虑事件时间和水印(watermarks)的处理。以下是修改前后的代码对比分析: 修改前的代码: val systemDS unitDS.map(dp > {dp.setDeviceCode(DeviceCodeEnum.fro…

Macos 远程登录 Ubuntu22.04 桌面

这里使用的桌面程序为 xfce, 而 gnome 桌面则测试失败。 1,安装 在ubuntu上,安装 vnc server与桌面程序xfce sudo apt install xfce4 xfce4-goodies tightvncserver 2,第一次启动和配置 $ tightvncserver :1 设置密码。 然后修改配置&#xff1a…

JVM 之对象的结构与创建

1.对象的创建 1.1类加载 当Java 虚拟机遇到一条字节码 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到 一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那 必须先执行相应的类加载过…

Python MySQL 教程

Python MySQL 教程 引言 Python 是一种广泛使用的高级编程语言,以其简洁明了的语法和强大的功能而闻名。MySQL 是一种流行的开源关系数据库管理系统 (RDBMS),广泛用于各种应用程序,包括数据密集型 Web 应用程序。Python MySQL 教程将指导您如何使用 Python 语言与 MySQL 数…

C# .net6使用Hangfire

首先我们先来了解什么是Hangfire? Hangfire 是一个用于 .NET 的任务调度库,允许你在后台运行任务,而不需要依赖外部的任务队列服务或复杂的基础设施。它简化了后台任务的创建、调度和管理过程,使得在 .NET 应用程序中处理长期运行…

flutter Android端权限

flutter 中权限请求path_provider Android 6.0 - 10.0 (API level 23 - 29)Android 11 (API level 30)具体实现示例注意事项 在 Flutter 中使用 path_provider 插件获取除本应用外所有的 PDF 文件,对于不同的 Android 版本(从 Android 6.0 到 Android 14…

我不是一个人在战斗

这也是一个老生常谈的话题,但很多人还是出不出单兵作战的怪圈,不断让单兵作战的孤独感、团队协作的无助感困惑自己,困惑整个团队,造成心气一直不高,严重影响工作效率。对此我还是坚持去年的观点:坚持宽松、…

【系统架构设计】操作系统(一)

操作系统(一) 操作系统的类型和结构操作系统基本原理进程管理进程三态模型挂起状态进程互斥 / 进程同步前趋图进程调度死锁 存储管理设备管理文件管理作业管理 操作系统原理的关键在于“一个观点、两条线索”:一个观点是以资源管理的观点来定…

简谈设计模式之代理模式

代理模式是一种结构型设计模式, 主要用于为其他对象提供一种代理, 以控制对这个对象的访问. 代理模式可以在不修改目标对象的前提下, 通过代理对象在访问目标对象之前或之后增加额外的操作 代理模式结构 抽象主题: 定义了真实主题和代理的共同接口, 这样客户端就可以通过接口…

【算法笔记自学】第 9 章 提高篇(3)——数据结构专题(2)

9.1树与二叉树 #include <cstdio>int main() {int n, m;scanf("%d%d", &n, &m);printf(n m 1 ? "Yes" : "No");return 0; } 9.2二叉树的遍历 #include <cstdio> #include <vector> using namespace std;const int…