flask-4
数据库驱动(drivers)模块:pymysql、MySQLDB
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 # 如果上面一句代码安装失败,去掉-c后面的选项内容。
pip安装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连接配置操作
models.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", # 如果底层驱动是pymysql url="mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4", # 如果底层驱动是MysqlDB echo=True, # 当设置为True时会将orm语句转化为sql语句打印,一般debug的时候可用 pool_size=8, # 连接池的大小,默认为5个,设置为0时表示连接无限制 pool_recycle=60*30 # 设置时间以限制数据库多久没连接自动断开 ) DbSession = sessionmaker(bind=engine) session = DbSession() # 创建数据基类 Model = declarative_base()
manage-SQLAlchemy的基本使用.py,代码:

import models class Student(models.Model): # 声明表名 __tablename__ = "student" id = models.Column(models.Integer, primary_key=True,) name = models.Column(models.String(255)) sex = models.Column(models.Boolean) age = models.Column(models.SmallInteger) class_name = models.Column("class",models.String(255),) description = models.Column(models.Text) def __repr__(self): # 打印, django中是__str__ return f"<{self.name} {self.__class__.__name__}>" if __name__ == '__main__': # 如果没有提前声明模型中的数据表,则可以采用以下代码生成数据表, # 如果数据库中已经声明了有数据表,则不会继续生成(类似数据迁移django) models.Model.metadata.create_all(models.engine) # # 获取模型对应表的所有数据 # student_list = models.session.query(Student).all() # # # 循环输出 # for student in student_list: # print(student, student.id, student.name ,student.age) # # 获取一条数据[参数为主键,如果查询不到,则返回结果为None] # student = models.session.query(Student).get(105) # if student: # print(student, student.name, student.class_name) # else: # print("查无此人") # # 按条件查询 # student_list = models.session.query(Student).filter(Student.sex==True, Student.class_name=='301').all() # print(student_list) # # 添加一条数据 # student = Student( # name="张三丰", # sex=True, # age=17, # class_name="305", # description="太极生两仪..." # ) # # models.session.add(student) # models.session.commit() # # 修改操作 # student = models.session.query(Student).filter_by(name="张三丰").first() # if student: # student.name="张四封" # student.age = 21 # models.session.commit() # # 删除一条数据操作 # student = models.session.query(Student).filter_by(name="xiaohui").first() # models.session.delete(student) # models.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="美美的..",), # ] # # models.session.add_all(student_list) # models.session.commit() # # 更新多条数据 # models.session.query(Student).filter(Student.class_name=="303").update({Student.age: Student.age+1}) # models.session.commit() # # 删除多条数据 # models.session.query(Student).filter(Student.id > 100).delete() # models.session.commit() # # 原生SQL语句 # # 读 # cursor = models.session.execute('select * from student') # # 一条 # data = cursor.fetchone() # print(data) # # 多条 # data_list = cursor.fetchall() # print(data_list) # 写[添加、删除、修改] cursor = models.session.execute( 'insert into student(name, class, age, sex, description) values(:name, :class, :age, :sex, :description)', params={ "name": "xiaohong", "class": "307", "age": 19, "sex": 0, "description": ".....", }) models.session.commit() print(cursor.lastrowid) # 获取最后添加的主键ID