请求上下文和应用上下文都是保存在global.py
请求上下文:request
和session
应用上下文:current_app
和g
token
口令
column
字段
paginate
分页
1.ORM(Sqlalchemy)概述(理解)
ORM:对象关系映射模型
ORM会将我们模型类文件中的指令翻译成SQL语句,去操作数据库,而且我们不需要关心数据库是哪一种数据库.
缺点:
1/由于不是直接通过sql
操作数据库,所以有性能损失
优点:
1/对数据库的操作都转化成对类,属性和方法的操作.
2/不用编写各种数据库的sql语句
.
3/不在关注,使用的是mysql
、oracle
...等数据库
特点总结:
类名称---->数据库表名
类属性---->数据库字段
类的对象----->数据库表中的一行一行数据
2.ORM操作流程(掌握)
操作流程:
1/安装扩展
pip install flask-sqlalchemy
pip install flask_mysqldb/pymysql
2/设置数据库的配置信息
3/创建sqlalchemy
对象db,关联app
4/编写模型类,字段,继承自db.Model
5/操作数据库----增删改和查询
3.ORM操作注意(理解)
1/因为SQLALChemy
去app身上读取了配置信息,所以需要设置到app.config身上
2/数据库的链接信息
如果安装的是flask_mysqldb,那么连接信息:
mysql://root(用户名):mysql(密码)@127.0.0.1(ip地址):3306(端口号)/data36(数据库名字)
如果安装的是flask_pymysql,那么连接信息:
mysql+pymysql://root(用户名):mysql(密码)@127.0.0.1(IP地址):3306(端口号)/data36(数据库名字)
3/编写的模型类必须继承自db.Model才能被映射
4/如果不指定表名称,默认生成的就是模型类的小写,如果需要自己指定表名称使用__tablename__="表名称"
5/删除继承自db.Model的表db.drop_all()
6/ORM在进行映射的时候不能生成数据库的,我们需要在数据库中建立相对应的数据库.然后再进行ORM操作.
4. 数据库增删改(掌握)
4.1增删改
全部都是使用db.session
操作
常见方法:
db.session.add(obj)
添加单个对象
db.session.delete(obj)
删除单个对象
db.session.add_all([obj1,obj2])
增加多个对象
db.session.commit()
提交会话
db.drop_all()
删除继承自db.Model的所有表
db.create_all()
创建继承自db.Model的所有表
对象.属性 = 值
修改数据
其他:
db.session.rollback()
回滚
db.session.remove()
移除会话
案例:
编写两个模型类,一个角色(比如经理这个职位可以由好多人来扮演这个角色)模型类,还有一个用户模型类(外键写在多方)
关系:一对多
为了写命令方便,我们可以使用ipython3进行操作
将py程序里面的所有东西导入一下
from demo02role_user import *
导入之后我们就可以将命令在终端里面进行练习操作了
注意:在增加.删除之后要提交,数据库才会进行更改.
我们在打印对象的时候,默认显示的是对象和主键值.如果想要看到指定的信息,那么看下面操作:
如果一个类继承自object,那么重写__str__
方法即可,
如果是继承自db.Model,那么需要重写__repr__
方法.
5.数据库基本查询(掌握)
全部都是通过,模型类.query来进行的
常见的12条语句:(练习至少3遍)
先来回顾一下数据库增加,删除,修改操作:增加:user = User(name='laowang')
db.session.add(user)
db.session.commit()
修改:user.name = 'xiaohua'
db.session.commit()
删除:db.session.delete(user)
db.session.commit()
以下12条查询语句:特点:模型.query: 得到了所有模型的数据的结果集对象模型.query.过滤器: 过滤出了想要的数据,还是一个查询结果集对象模型.query.过滤器.执行器: 取出了结果集中的内容
查询所有用户数据User.query.all()
查询有多少个用户User.query.count()
查询第1个用户User.query.all()[0]
查询id为4的用户[3种方式]User.query.get(4)
User.query.filter_by(id = 4).first()
User.query.filter(User.id == 4).first()
查询名字结尾字符为g的所有数据[开始/包含]User.query.filter(User.name.endswith('g')).all()
User.query.filter(User.name.startswith('g')).all()
User.query.filter(User.name.contains('g')).all()
查询名字不等于wang的所有数据[2种方式]
User.query.filter(User.name != 'wang').all()
User.query.filter(not_(User.name == 'wang')).all()
查询名字和邮箱都以 li 开头的所有数据[2种方式]User.query.filter(User.name.startswith('li'),User.email.startswith('li')).all()
User.query.filter(and_(User.name.startswith('li'),User.email.startswith('li'))).all()
查询password是 123456
或者 email
以 itheima.com
结尾的所有数据User.query.filter(or_(User.password == '123456',User.email.endswith('itheima.com'))).all()
查询id为 [1, 3, 5, 7, 9] 的用户列表User.query.filter(User.id.in_([1,3,5,7,9])).all()
查询name为liu的角色数据user = User.query.filter(User.name == 'liu').first()
role = Role.query.filter(Role.id == user.role_id).first()
查询所有用户数据,并以邮箱排序User.query.order_by(User.email).all()
User.query.order_by(User.email.desc()).all()
每页3个,查询第2页的数据paginate = User.query.paginate(page, per_page,Error_out)
paginate = User.query.paginate(2,3,False)
page
: 哪一个页per_page
: 每页多少条数据Error_out
: False 查不到不报错
paginate(page,per_page,Error_out)
page表示要查询的页数,per_page表示每页有多少条数据,Error_out建议写成False,查不到不会报错
paginate.pages
总页数
paginate.page
当前页
paginate.items
当前页数所有的对象
注意点:
User.query.get(4)
get里面放的是主键,查不到也不报错
过滤是可选的,执行时必选的
User.query.filter(User.id == 4).first()
可以取消列表
limit()
做限制,每页显示几条
Role.query.filter(Role.id==user.role_id).all()
里面的'='一定要写成两个
filter
里面都是写两个等于号==
6.数据库关系查询relationship(掌握)
简化操作
解释:为了方便数据库的关联查询
特点:
1/不会在数据库产生实体字段
2/关系属性需要在一方添加,外键在多方
3/外键添加在一方,并且关系属性的使用需要依赖于外键
需求:
1/如果知道了角色的情况下,能否快速查询出,哪些用户扮演了该角色
原始查询方法:
role = Role.query.get(1)
users=User.query.filter(User.role_id == role.id).all()
快速查询:
使用了relationship添加关系属性,就可以快速查询了
格式(添加在程序中的):
users=db.relationship('多方的模型类')
在程序中添加了上面的语句后,不需要重新执行,只需要把终端里面退出当前,再进入就好了.因为使用了relationship不会在数据库产生实体字段
使用格式(ipython3使用的):
role = Role.query.get(1)
users=role.users
给role添加了一个users属性,那么查询的方式是role.users
7.数据库反向查询backref(掌握)
解释:/如果知道了用户的情况下,能否快速查询出,哪些该用户扮演了哪个角色
原始查询方法:
user= User.query.get(1)
role=Role.query.filter(Role.id==user.role_id).first()
role=Role.query.get(user.role_id)
快速查询:
使用backref添加反向属性,就可以快速查询了
格式:
给user添加了一个role属性,那么查询的方式是user.role
users=db.relationship('多方的模型类',backref="role(自己随意命名)")
快速查询:
user=User.query.get(1)
role=user.role
8.数据库懒查询lazy(了解)
解释:一旦使用了relationship和backref,那么系统会自动做子查询
子查询(subquery):查询了一方,就会自动的将关联的一方查询出来
动态查询(dynamic):只有用到了才去查询(得到一个结果集,只有你去获取才能得到)
lazy的使用:
users=db.relationship('多方的模型类',backref="role(自己随意命名)",lazy='dynamic')
9.图书馆数据库搭建(掌握)具体看图书馆数据库系统代码.
分析图书馆案例:
1/数据库配置()
1.1作者模型(一方)
1.2书籍模型(多方)
2/添加测试数据
3/添加作者/书籍
4/删除作者/删除书籍
10.图书馆测试数据添加(掌握)
1/为了演示的方便,先删除所有的表,再创建
2/添加测试数据库
2.1生成数据
2.2把数据提交到用户的会话
2.3提交会话
3/准备数据,并且将数据提交给用户会话
3.1提交会话
11.图书馆测试数据显示(掌握)
实现过程:
1/查询所有的作者信息
2/携带作者信息,渲染页面
3/建立html页面,可以遍历作者信息,然后再遍历作者书籍的信息.统一进行展示
12.图书馆添加数据(掌握)
所有的语句都会被映射成SQL语句,所以才会进行数据库的操作.
添加的逻辑分析:
1/如果作者存在,书籍存在,不能添加.
2/如果作者存在,书籍不存在,可以添加
3/如果作者不存在,可以添加
实现过程:
1/获取提交的数据
1.1判断输入的内容是否为空
2/根据作者的信息,查询作者对象
3/判断作者是否存在
4/通过书籍名称查询书籍对象,获取该作者,有没有写过该书
5/判断书籍对象是否存在
6/重定向到首页展示
13.图书馆删除书籍(掌握)
删除的实现过程:
1/根据书籍编号取出书籍对象
2/删除书籍
3/重定向到页面展示
14.图书馆删除作者(掌握)
实现过程:
1/根据作者编号取出作者对象
2/遍历作者书籍,删除
3/删除作者,提交数据库
4/重定向展示页面
15.图书馆CSRFProtect应用(掌握)
作用:防止csrf攻击的(到以后会给大家展示源代码的校验过程)
使用步骤:
1/导入类CSRFProtect
2/使用CSRFProtect保护app
一旦使用POST,PUT,DELETE,PATCH方式提交,的时候就需要校验csrf_token
3/需要设置SECRET_KEY,用来加密csrf_token
4/设置csrf_token到列表中
16.表结构多对多分析(掌握)
多对多的关系,通过一张中间表
实现的难点再与中间表
有了中间表之后,中间表和每一张表都被拆分成了一对多的关系,外键应该写在多方,所以中间表写外表
解释:多对多的更关系,一般会被拆分成两张一对多的表
17.表结构多对多代码演练(掌握)
中间表:
tb_student_course = db.Table(
"tb_student_course",
db.Column("student_id",db.Integer,db.ForeignKey("students.id"))
db.Column("courses_id",db.Integer,db.ForeignKey("courses.id"))
)
中间表写在前面的时候,会找不到students和courses的表名,有两种解决办法:
1/可以将中间表放在后面,
2/可以写类名Student.id
18.表结构模板代码分析(了解)
一对多
多对多
自关联一对多(了解)
自关联多对多(了解)
自关联就是在一张表中发生关系
在工作的时候如果考虑到了某种情况用的到上面的关系,可以查相关模板代码,在使用的时候直接复制粘贴的时候就行了.
19.数据库迁移(掌握)
作用:动态的改变数据库的表结构
目的:当数据库的表结构发生变化之后,如果直接删除原有的数据,再添加新的数据,有可能导致数据丢失.做升级操作
注意点:
1/是为了备份表结构,而不是数据
2/如果想要备份数据,需要使用工具,Navicat,mysqlworkbench,等等
3/更新的过程数据一般不会丢失,做降级的时候需要谨慎操作,用工具备份
操作流程:
1/安装扩展
pip install flask_script
pip install flask_migrate
2/导入三个类
from flask_script import Manager
from flask_migrete import Migrate,MigrateCommand
3/通过Manager类创建对象manager,管理app
manager = Manager(app)
4/使用Migrate,关联db,app
Migrate(app,db)
5/给manager添加一条操作命令
manager.add_command('db',MigrateCommand)
6/相关迁移命令
生成迁移文件夹(一次就好)
python xxx.py db init
将模型类生成迁移脚本(重复执行,每次改变都要执行)
python xxx.py db migrate -m '注释'
在版本文件夹中生成一个版本,名字是自动生成的一串数字和你注释的内容
将版本更新到数据库执行下面的命令
将迁移脚本更新到数据库中(重复执行,每次改变都要执行)
python xxx.py db upgrade[version]
此处的version可选,veision就是版本
退回到之前的脚本(降级操作)
python xxx.py db downgrade[version]
上面的更新和退回可以不断的在版本之间穿梭的.
升级是更新一个版本,降级是回退一个版本
其他命令:
查看最新的版本的命令
python xxx.py db show
查看当前版本
python xxx.py db current
查看所有的历史版本
python xxx.py db history