> 文章列表 > Python轻量级Web框架Flask(7)——翻页功能/多表操作

Python轻量级Web框架Flask(7)——翻页功能/多表操作

Python轻量级Web框架Flask(7)——翻页功能/多表操作

1、使用paginate实现分页:

  • 基础指令(新建对象)
    在这里插入图片描述
  • 基础指令(使用对象属性)
    在这里插入图片描述
    在这里插入图片描述

2、几种类型的表操作

  • 一对一:例如一个人只能有一张身份证。
  • 一对多:例如班级和学生(一个班级可以对应多个学生,而每个学生只能有一个班级,对于学生而言这就是一对一的关系)
  • 多对多:例如一个学生可以选择多门选修课,一门选修课对应多个学生(多对多关系需要有一个中间表,多对多关系可以分解为两个一对多关系)

3、一对多操作:

  • 现在通过一对多的关系(一个班级可以有多个学生)在数据库建表,进行说明:
  • 项目模板借鉴:Python轻量级Web框架Flask(6)中的项目模板

3.1、代码展示:

__init __代码:

# __init__.py : 初始化文件,创建Flask应用
from flask import Flask
from .views import blue
from .exts import init_extsdef creat_app():app = Flask(__name__)# 注册蓝图app.register_blueprint(blueprint=blue)# 配置数据库# db_uri = 'sqlite:///sqlite3.db'db_uri = 'mysql+pymysql://root:123456@localhost:3306/flaskdb2' # mysql的配置,要记得在mySQL中配置flaskdb2数据库app.config['SQLALCHEMY_DATABASE_URI'] = db_uriapp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 禁止对象追踪修改# 初始化插件init_exts(app=app)return app

exts代码:

from flask_sqlalchemy import SQLAlchemy # ORM
from flask_migrate import Migrate   # 数据迁移db = SQLAlchemy()
migrate = Migrate()def init_exts(app):db.init_app(app=app)migrate.init_app(app=app,db=db)

models 代码

# models.py : 模型,数据库
from .exts import db# 建立一对多的多表关系:班级和学生(1:N)
# 班级表:
class Grade(db.Model):__tablename__ = 'grade'   # 表名# 定义表字段id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(30), unique=True, index=True)# 建立关联:#   第一个参数:关联的模型名(表名)#   第二个参数:反向引用的名称,grade对象#             让student反过来得到grade对象的名称:student.grade#   第三个参数:懒加载(不用的时候不调用,用到之后才调用)# 注意:这里的students不是字段,是类属性students = db.relationship('Student', backref='grade', lazy=True)  # 这里Student因为在之后定义,所以可以先用字符串来替代
# 学生表:
class Student(db.Model):__tablename__ = 'student'id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(30), unique=True)age = db.Column(db.Integer)# 外键:跟Grade表中的id字段关联gradeid = db.Column(db.Integer, db.ForeignKey(Grade.id))

完成了上面的步骤之后,下一步就是经典的数据迁移步骤:
1、在pycharm终端中把整个项目文件拖进去,然后在终端执行:flask db init
2、在终端继续执行:flask db migrate
3、在终端继续执行:flask db upgrade
上述步骤执行结束之后,models中的表就已经生成了,但是其中还没有添加数据,此阶段项目概览如下。

3.2、项目概览:

Python轻量级Web框架Flask(7)——翻页功能/多表操作

3.3、多表操作:

多表操作主要是在views.py文件中操作

# 在views.py中放路由和视图函数
import randomfrom flask import Blueprint, request, render_template
from .models import * #后面是用views来控制数据库的,所以要在views中导入models文件# 蓝图
blue = Blueprint('user', __name__)@blue.route('/')
def index():return 'index'# 一对多添加数据:先给唯一项添加数据,然后再给多项添加数据,因为外键绑定在多项上
@blue.route('/add_grade/')
def add_grade():# 添加班级grades = []for i in range(5):grade = Grade()grade.name = f'HuaQing{i}班'grades.append(grade)try:db.session.add_all(grades)db.session.commit()except Exception as e:print(f'e:{e}')db.session.rollback()db.session.flush()return 'add_Ok!'
@blue.route('/add_stu/')
def add_stu():l = ['张', '刘', '王', '赵']# 添加学生stus = []for i in range(11):stu = Student()stu.name = str(l[random.randint(0, 3)]) + str(i)stu.age = random.randint(18,21)stu.gradeid = random.randint(1,2)stus.append(stu)print(stus)try:db.session.add_all(stus)db.session.commit()except Exception as e:print(f'e:{e}')db.session.rollback()db.session.flush()return 'add_Ok!'# 修改:注意修改之前要先查找数据
@blue.route('/updatestu/')
def upset_stu():stu = Student.query.first()stu.name = '改名六六六'try:db.session.commit()except Exception as e:print('e:', e)db.session.rollback()db.session.flush()return 'XiuGaiOk!'# 删除:注意删除之前要先查找数据
@blue.route('/del_stu/')
def delete_stu():stu = Student.query.first()db.session.delete(stu)try:db.session.commit()except Exception as e:print('e:', e)db.session.rollback()db.session.flush()return 'ShanChuOk!'# 查询:因为在models中有设置,所以这里可以反向引用
@blue.route('/get/')
def get():# 查询id为40的学生所在的班级stu = Student.query.get(40)print(stu.name, stu.age)print(stu.gradeid, stu.grade, stu.grade.name,stu.grade.id)# 查询gradeid是2的所有学生grade = Grade.query.get(2)print(grade.name,grade.students)   # 这里的students在models中的Grade中最后定义的return 'getstuOK!'

4、多对多操作:

  • 多对多继续用上面一对多的项目框架

  • 设计多对多数据表:设计一个用户和电影之间多对多的表,中间表设计为收藏表(一个用户可以收藏多个电影,一个电影也可以被多个用户收藏),表格关系如下:
    在这里插入图片描述

  • 什么是正向引用,什么是反向引用:A表和B表关联,A调用B,对于A来说是正向引用,对于B来说是反向引用。

  • 多对多中表格的建立可以通过下述的标准代码方法进行,也可以设置两个一对多来实现。

4.1、举例实现多对多操作:

1、 models中的代码:

# models.py : 模型,数据库
from .exts import db
# ---------------------------------多对多---------------------------------
# 中间表(收藏表):注意在多对多关系中中间表要写在其他表的最前面,而且表格写法也和普通表不一样。
# 中间表中可以不用单独设置主键,这样就可以把关联的两个表的主键作为主键,在数据库中如果有两个主键,则这两个主键的组合代表了一行数据。
collect = db.Table( # db中的还有一个Table的类,用它可以创建一个Table对象'collects',# 表名# 注意,下面代码中'usermodel.id'中usermodel是UserModel的小写表示,由于类的特性(没法调用写在后面的类),在模型中可以先用字符串表示。db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),db.Column('movie_id', db.Integer, db.ForeignKey('movie.id'), primary_key=True),
)
# 普通表(用户表):
class User(db.Model):__tablename__ = 'users' # 表名id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(30))age = db.Column(db.Integer)
# 普通表(电影表):
class Movie(db.Model):__tablename__ = 'movies' # 表名id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(30))# 关联:这个关联可以建立在电影表中,也可以建立在用户表中,但是参数就有所不同了。# secondary=collect:设置中间表movie_users = db.relationship('UserModel', backref='user_movies', lazy=True, Secondary=collect)'''lazy属性:懒加载,可以延迟在使用关联属性的时候才建立关联lazy='dynamic':会返回一个query对象(查询集),可以继续使用其他查询方法,如all()lazy='select':首次访问到属性的时候,就会全部加载该属性的数据lazy='joined':在对关联的两个表进行join操作,从而获取所有相关的对象lazy='True':返回一个可用的列表对象,同select'''

2、数据迁移:因为在一对多中已经数据迁移过了,所以就不用初始化了

在终端中该项目路径下执行:flask db migrate	此时会在migrations中的versions中出现一个新编号的py文件
在终端中该项目路径下执行:flask db upgrade 此时会在数据库中生成这三个表

3、多对多表格操作:这部分主要在views文件中完成

# 在views.py中放路由和视图函数
import randomfrom flask import Blueprint, request, render_template
from .models import * #后面是用views来控制数据库的,所以要在views中导入models文件# 蓝图
blue = Blueprint('user', __name__)@blue.route('/')
def index():return 'index'
# ---------------------------------多对多---------------------------------
# 添加数据
@blue.route('/add_user/')
def add_users():l = ['张', '刘', '王', '赵']# 添加用户users = []for i in range(1, 6):user = User()user.name = str(l[random.randint(0, 3)]) + str(i)user.age = random.randint(8,100)users.append(user)try:db.session.add_all(users)db.session.commit()except Exception as e:print(f'e:{e}')db.session.rollback()db.session.flush()return 'add_Ok!'
@blue.route('/add_movie/')
def add_movies():l = ['流浪地球', '阿凡达', '蜡笔', '拉丁哇']# 添加电影movies = []for i in range(1, 6):movie = Movie()movie.name = str(l[random.randint(0, 3)]) + str(i)movies.append(movie)try:db.session.add_all(movies)db.session.commit()except Exception as e:print(f'e:{e}')db.session.rollback()db.session.flush()return 'add_Ok!'
@blue.route('/add_collect/')
def add_collects():# 用户收藏电影user = User.query.get(1)movie = Movie.query.get(1)user.user_movies.append(movie)db.session.commit()return 'add_Ok!'# 查询
@blue.route('/get_collect/')
def get_collect():# 查找某个用户收藏的所有电影user = User.query.get(1)print(user.user_movies)print(Movie.query.get(5).movie_users)return 'query_OK!'# 修改操作和单表操作一样# 删除:
@blue.route('/del_user/')
def del_users():user = User.query.get(1)# 删除了user中的id=1,则在collect表中和1相关的数据也都会被删除# 删除操作只会影响关联表,不会影响其他表db.session.delete(user)db.session.commit()return 'OK!'

总结:

  • 1、不论是单表操作还是多表操作流程都一样:
    • 首先在models中建表。(在一对多的情况下,外键是写在多的表格中)
    • 然后在终端进行“数据迁移”(就是把flask模型中建的表放到电脑的数据库中),这一步就要看你__init __中db_uri连接的是什么数据库了。
    • 数据迁移要注意有过初始化的就不用重复初始化。
    • 数据表的:增、删、改、查都是在views中进行的,要注意的一点是一对多和多对多中数据增加是有区别的,多对多中,对中间表进行添加数据时和普通表添加数据有区别。

美剧