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

1、使用paginate实现分页:

  • 基础指令(新建对象)
    在这里插入图片描述
  • 基础指令(使用对象属性)
    Python轻量级Web框架Flask(7)——翻页功能/多表操作_第1张图片
    Python轻量级Web框架Flask(7)——翻页功能/多表操作_第2张图片

2、几种类型的表操作:

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

3、一对多操作:

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

3.1、代码展示:

__init __代码:

# __init__.py : 初始化文件,创建Flask应用
from flask import Flask
from .views import blue
from .exts import init_exts

def 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_uri
    app.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.3、多表操作:

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

# 在views.py中放路由和视图函数
import random

from 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、多对多操作:

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

  • 设计多对多数据表:设计一个用户和电影之间多对多的表,中间表设计为收藏表(一个用户可以收藏多个电影,一个电影也可以被多个用户收藏),表格关系如下:
    Python轻量级Web框架Flask(7)——翻页功能/多表操作_第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 random

from 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中进行的,要注意的一点是一对多和多对多中数据增加是有区别的,多对多中,对中间表进行添加数据时和普通表添加数据有区别。

你可能感兴趣的:(Flask框架学习笔记,flask,python,前端)