flask框架(三)

时间:2022-06-26
本文章向大家介绍flask框架(三),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

请求上下文和应用上下文都是保存在global.py

请求上下文:requestsession

应用上下文:current_appg

token口令

column字段

paginate分页

1.ORM(Sqlalchemy)概述(理解)

ORM:对象关系映射模型

ORM会将我们模型类文件中的指令翻译成SQL语句,去操作数据库,而且我们不需要关心数据库是哪一种数据库.

缺点:

1/由于不是直接通过sql操作数据库,所以有性能损失

优点:

1/对数据库的操作都转化成对类,属性和方法的操作.

2/不用编写各种数据库的sql语句.

3/不在关注,使用的是mysqloracle...等数据库

特点总结:

类名称---->数据库表名

类属性---->数据库字段

类的对象----->数据库表中的一行一行数据

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 或者 emailitheima.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