7-flask框架-数据库操作/数据的增删改
优点 :
-
只需要面向对象编程, 不需要面向数据库编写代码.
-
对数据库的操作都转化成对类/对象的属性和方法的操作. 字段--->属性, 关键字-> 操作方法
-
不用编写各种数据库的
sql语句
.
-
-
实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
-
不再需要关注当前项目使用的是哪种数据库。
-
通过简单的配置就可以轻松更换数据库, 而不需要修改代码.
-
缺点:
-
相比较直接使用SQL语句操作数据库,ORM需要把操作转换成SQL语句,所以有性能损失.
-
根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.
-
增加了学习成本,不同的ORM提供的操作不一样
SQLAlchemy是一个关系型数据库框架,它提供了高层的 ORM 和底层的原生数据库的操作。flask-sqlalchemy 是一个简化了 SQLAlchemy 操作的flask扩展。
SQLAlchemy:
2.1 安装 flask-sqlalchemy
使用清华源
pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple
安装flask-mysqldb时,注意
安装 flask-mysqldb的时候,python底层依赖于一个底层的模块 mysql-client 模块 如果没有这个模块,则会报错如下: Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-21hysnd4/mysqlclient/
解决方案:
sudo apt-get install 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
class Config(object): DEBUG = True SECRET_KEY = "*(%#4sxcz(^(#$#8423" # 数据库链接配置 = 数据库名称://登录账号:登录密码@数据库主机IP:数据库访问端口/数据库名称?charset=编码类型 dsn SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
- 其他设置
# 动态追踪修改设置,如未设置只会提示警告 SQLALCHEMY_TRACK_MODIFICATIONS = True #查询时会显示原始SQL语句 SQLALCHEMY_ECHO = True
- 配置完成需要去 MySQL 中创建项目所使用的数据库
mysql -uroot -p123
create database students charset=utf8mb4;
- 然后,将配置项加载到Flask对象中
from flask import Flask app = Flask(__name__) class Config(object): DEBUG = True # 数据库连接配置 # SQLALCHEMY_DATABASE_URI = "数据库类型://数据库账号:密码@数据库地址:端口/数据库名称?charset=utf8mb4" SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4" # 动态追踪修改设置,如未设置只会提示警告 SQLALCHEMY_TRACK_MODIFICATIONS = True # 查询时会显示原始SQL语句 SQLALCHEMY_ECHO = True app.config.from_object(Config) @app.route("/") def index(): return "ok!" if __name__ == '__main__': app.run(debug=True)
python中数据类型 | 说明 | |
---|---|---|
Integer | int | 普通整数,一般是32位 |
SmallInteger | int | 取值范围小的整数,一般是16位 |
BigInteger | int或long | 不限制精度的整数 |
Float | float | 浮点数 |
Numeric | decimal.Decimal | 普通数值,一般是32位 |
String | str | 变长字符串 |
Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
Unicode | unicode | 变长Unicode字符串 |
UnicodeText | unicode | 变长Unicode字符串,对较长或不限长度的字符串做了优化 |
Boolean | bool | 布尔值 |
Date | datetime.date | 日期 |
Time | datetime.datetime | 日期和时间 |
LargeBinary | str |
2.4
说明 | |
---|---|
primary_key | 如果为True,代表表的主键 |
unique | 如果为True,为这列创建唯一 索引,代表这列不允许出现重复的值 |
index | 如果为True,为这列创建普通索引,提高查询效率 |
nullable | 如果为True,允许有空值,如果为False,不允许有空值 |
default | 为这列定义默认值 |
三、数据库的基本操作
-
-
会话用 db.session 表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用 db.session.commit() 方法提交会话。
-
-
在 Flask-SQLAlchemy 中,查询操作是通过 query 对象操作数据。
-
四、模型类定义
在项目中会把,把模型创建到单独的文件中,但是现在我们先把模型类写在manage.py文件中
from flask import Flask app = Flask(__name__) class Config(object): DEBUG = True # 数据库连接配置 # SQLALCHEMY_DATABASE_URI = "数据库类型://数据库账号:密码@数据库地址:端口/数据库名称?charset=utf8mb4" SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4" # 动态追踪修改设置,如未设置只会提示警告 SQLALCHEMY_TRACK_MODIFICATIONS = True # 查询时会显示原始SQL语句 SQLALCHEMY_ECHO = True app.config.from_object(Config) """模型类定义""" from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy(app=app) # 等同于 # db = SQLAlchemy() # db.init_app(app) class Student(db.Model): """学生信息模型""" # 声明与当前模型绑定的数据表名称 __tablename__ = "db_students" # 字段定义 """ create table db_student( id int primary key auto_increment comment="主键", name varchar(15) comment="姓名", ) """ id = db.Column(db.Integer, primary_key=True,comment="主键") name = db.Column(db.String(15), comment="姓名") age = db.Column(db.SmallInteger, comment="年龄") sex = db.Column(db.Boolean, default=True, comment="性别") email = db.Column(db.String(128), unique=True, comment="邮箱地址") money = db.Column(db.Numeric(10,2), default=0.0, comment="钱包") def __repr__(self): return f"{self.name}<Student>" # 所有的模型必须直接或间接继承于db.Model class Course(db.Model): """课程数据模型""" __tablename__ = "db_course" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(64), unique=True, comment="课程") price = db.Column(db.Numeric(7, 2)) # repr()方法类似于django的__str__,用于打印模型对象时显示的字符串信息 def __repr__(self): return f'{self.name}<Course>' class Teacher(db.Model): """老师数据模型""" __tablename__ = "db_teacher" id = db.Column(db.Integer, primary_key=True, comment="主键") name = db.Column(db.String(64), unique=True, comment="姓名") option = db.Column(db.Enum("讲师", "助教", "班主任"), default="讲师") def __repr__(self): return f"{self.name}< Teacher >" @app.route("/") def index(): return "ok!" if __name__ == '__main__': with app.app_context(): # 检测数据库中是否存在和模型匹配的数据表。 # 如果没有,则根据模型转换的建表语句进行建表。 # 如果找到,则不会进行额外处理 db.create_all() app.run(debug=True)
with app.app_context(): # create_all()方法执行的时候,需要放在模型的后面 # 检测数据库中是否存在和模型匹配的数据表。 # 如果没有,则根据模型转换的建表语句进行建表。 # 如果找到,则不会进行额外处理 db.create_all()
5.2 删除表
db.drop_all() # 慎用,很给力的!!
5.3 代码实例
1 from flask import Flask 2 app = Flask(__name__) 3 4 class Config(object): 5 DEBUG = True 6 # 数据库连接配置 7 # SQLALCHEMY_DATABASE_URI = "数据库类型://数据库账号:密码@数据库地址:端口/数据库名称?charset=utf8mb4" 8 SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4" 9 # 动态追踪修改设置,如未设置只会提示警告 10 SQLALCHEMY_TRACK_MODIFICATIONS = True 11 # 查询时会显示原始SQL语句 12 SQLALCHEMY_ECHO = True 13 14 app.config.from_object(Config) 15 16 17 """模型类定义""" 18 from flask_sqlalchemy import SQLAlchemy 19 db = SQLAlchemy(app=app) 20 # 等同于 21 # db = SQLAlchemy() 22 # db.init_app(app) 23 24 class Student(db.Model): 25 """学生信息模型""" 26 # 声明与当前模型绑定的数据表名称 27 __tablename__ = "db_students" 28 # 字段定义 29 """ 30 create table db_student( 31 id int primary key auto_increment comment="主键", 32 name varchar(15) comment="姓名", 33 ) 34 """ 35 id = db.Column(db.Integer, primary_key=True,comment="主键") 36 name = db.Column(db.String(15), comment="姓名") 37 age = db.Column(db.SmallInteger, comment="年龄") 38 sex = db.Column(db.Boolean, default=True, comment="性别") 39 email = db.Column(db.String(128), unique=True, comment="邮箱地址") 40 money = db.Column(db.Numeric(10,2), default=0.0, comment="钱包") 41 42 def __repr__(self): 43 return f"{self.name}<Student>" 44 45 # 所有的模型必须直接或间接继承于db.Model 46 class Course(db.Model): 47 """课程数据模型""" 48 __tablename__ = "db_course" 49 id = db.Column(db.Integer, primary_key=True, comment="主键") 50 name = db.Column(db.String(64), unique=True, comment="课程") 51 price = db.Column(db.Numeric(7, 2)) 52 # repr()方法类似于django的__str__,用于打印模型对象时显示的字符串信息 53 def __repr__(self): 54 return f'{self.name}<Course>' 55 56 class Teacher(db.Model): 57 """老师数据模型""" 58 __tablename__ = "db_teacher" 59 id = db.Column(db.Integer, primary_key=True, comment="主键") 60 name = db.Column(db.String(64), unique=True, comment="姓名") 61 option = db.Column(db.Enum("讲师", "助教", "班主任"), default="讲师") 62 63 def __repr__(self): 64 return f"{self.name}< Teacher >" 65 66 @app.route("/") 67 def index(): 68 return "ok!" 69 70 if __name__ == '__main__': 71 with app.app_context(): 72 # db.drop_all() 73 # 检测数据库中是否存在和模型匹配的数据表。 74 # 如果没有,则根据模型转换的建表语句进行建表。 75 # 如果找到,则不会进行额外处理 76 db.create_all() 77 app.run(debug=True)
六 、数据操作
6.1 添加数据
添加一条数据
student1 = Student(name="小明", sex=True, age=17, email="123456@qq.com", money=100) db.session.add(student1) db.session.commit() #再次插入 一条数据 student2 = Student(name='小红', sex=False, age=13, email="16565666@qq.com", money=600) db.session.add(student2) db.session.commit()
一次插入多条数据
st1 = Student(name='wang',email='wang@163.com',age=22) st2 = Student(name='zhang',email='zhang@189.com',age=22) st3 = Student(name='chen',email='chen@126.com',age=22) st4 = Student(name='zhou',email='zhou@163.com',age=22) st5 = Student(name='tang',email='tang@163.com',age=22) st6 = Student(name='wu',email='wu@gmail.com',age=22) st7 = Student(name='qian',email='qian@gmail.com',age=22) st8 = Student(name='liu',email='liu@163.com',age=22) st9 = Student(name='li',email='li@163.com',age=22) st10 = Student(name='sun',email='sun@163.com',age=22) db.session.add_all([st1,st2,st3,st4,st5,st6,st7,st8,st9,st10]) db.session.commit()
6.2 删除数据
# 方法1[先查询后删除,2条语句] # 先查询出来 student = Student.query.first() print(student) # 再进行删除 db.session.delete(student) db.session.commit() # 方法2【一条语句执行,性能更好更高效,在数据改动时添加条件才进行操作,这种用法就是乐观锁】 # 乐观锁和悲观锁 Student.query.filter(Student.id > 5).delete() db.session.commit()
6.3 更新数据
# 先查询数据,然后进行更新,2条语句 stu = Student.query.first() stu.name = 'dong' db.session.commit() # 直接根据条件更新,一条语句[乐观锁] Student.query.filter(Student.name == 'chen').update({'money': 1998}) db.session.commit() # 字段引用[利用当前一条数据的字典值进行辅助操作,实现类似django里面F函数的效果] Student.query.filter(Student.name == "zhang").update({"money":Student.money+1000 * Student.age}) db.session.commit()