Flask Models进阶 多表

Flask Models进阶 多表

'''
	多表查询时,db.relationship在哪边,哪边就是正向
	正向查找  关联关系名
	反向查找  backref
	
	# 班级表
	class Grade(db.Model):
        __tablename__ = 'grade'  # 表名
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(30), unique=True)
        student = db.relationship('Student', backref='grade', lazy=True)


    # 学生表		
    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))
        
        
	如 班级和学生 db.relationship在班级表中
	班级表去查学生 就是正向查找  Grade.query.get(1).student  就能拿到班级id为1的所有的学生
	学生表去查班级 就是反向查找  Student.query.get(1).grade  就能获取到该学生所在的班级的数据对象 Student.query.get(1).grade.name就可以获取班级的名称
	
	注意:
		要和django的orm区分开,django中外键字段在的一边是正向
			正向查找 外键字段
			反向查找 表名小写 + _set
			
'''

一对一关系

一对多关系

'''
	注意 外键建在多的一边 学生多所以外键在学生表
'''

案例

# 多表关系
# 一对多
# 班级:学生 = 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)
    # 建立关联
    # 第一个参数:关联的模型名(表)
    # 第二个参数:反向引用的名称,让student去反过来得到grade对象的名称 student.grade
    # 第三个参数:懒加载
    # 这里的student不是字段,
    student = db.relationship('Student', backref='grade', lazy=True)
    # 第一个参数关联哪张表,第二个参数:反向查找是用的关键字,第三个参数:懒加载


# 学生表
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))
# 一对多
# 增加数据
@blueprints1.route('/addgrade/')
def add_grade():
    # 添加班级
    grades = []
    for i in range(10):
        grades.append(Grade(name='LCX' + str(i)))
    try:
        db.session.add_all(grades)
        db.session.commit()
    except Exception as e:
        print(e)
        db.session.rollback()
        db.session.flush()
        return e
    return 'OK!'


@blueprints1.route('/addstu/')
def add_stu():
    # 添加学生
    students = []
    for i in range(10):
        students.append(Student(name='kunkun{}'.format(i), age=i, gradeid=random.randint(1, 3)))
    try:
        db.session.add_all(students)
        db.session.commit()
    except Exception as e:
        print(e)
        db.session.rollback()
        db.session.flush()
        return e
    return 'OK!'


# 修改
# 这里就展示学生的修改,班级的修改是一样的
@blueprints1.route('/updatestu/')
def update_stu():
    stu = Student.query.first()
    stu.age = 100
    db.session.commit()
    return 'OK!'


# 删除学生
@blueprints1.route('/delstu/')
def del_stu():
    stu = Student.query.first()
    db.session.delete(stu)
    db.session.commit()
    return 'OK!'


# 删除班级
@blueprints1.route('/delgrade/')
def del_grade():
    '''
        删除班级后,对应的班级里的学生的外键字段会变成空(null)
    '''
    grade = Grade.query.first()
    db.session.delete(grade)
    db.session.commit()
    return 'OK!'


# 查询
@blueprints1.route('/getstu/')
def get_stu():
    # 查询某个学生所在的班级 如id为3的学生所在的班级
    stu = Student.query.get(3)
    print(stu.name, stu.age, stu.gradeid, stu.grade)
    # kunkun2 2 3 <Grade 3>
    print(stu.grade.id, stu.grade.name)
    # 3 LCX2

    # 查询某个班级下的所有学生 如班级id为2下的所有学生
    grade = Grade.query.get(2)
    print(grade.name)  # LCX1
    print(grade.student)  # 所有学生 里面的是学生对象,可以用for循环得到每一个学生对象
    # [<Student 4>, <Student 5>, <Student 6>, <Student 7>, <Student 9>, <Student 10>]
    for stud in grade.student:
        print(stud.name)
    return 'OK!'

多对多

案例

# 多对多
# 用户收藏电影
# 用户 : 电影 = N : M

# 中间表(第三张表)最好是写在另外2张表的上面: 收藏表
collects = db.Table(
    'collects',  # 第三张表的名称
    db.Column('userid', db.Integer, db.ForeignKey('usermodel.id'), primary_key=True),
    # 第一个参数:字段名,第二个参数:字段类型,第三个参数:外键关联(使用表名小写.id的形式),第四个参数:设为主键
    db.Column('movie', db.Integer, db.ForeignKey('movie.id'), primary_key=True),
)


# 用户表
class UserModel(db.Model):
    __tablename__ = 'usermodel'
    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__ = 'movie'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30))
    # 关联关系
    # secondary = collect 设置中间表
    usermodel = db.relationship('UserModel', backref='movies', lazy='dynamic', secondary=collects)
    # 第一个参数关联哪张表,第二个参数:反向查找是用的关键字,第三个参数:懒加载


'''
lazy属性:
懒加载,可以延迟在使用关联属性的时候才建立关联 (建立关联时需要消耗资源,懒加载防止了一直消耗资源)
    lazy= 'dynamic ':会返回一个query对象(查询集),可以继续使用其他查询方法,如all().
    lazy='select':首次访问到属性的时候,就会全部加载该属性的数据.
    lazy='joined ':在对关联的两个表进行join操作,从而获取到所有相关的对象
    lazy=T&ue:返回一个可用的列表对象,同select

'''
1.准备数据
# 添加用户数据
@blueprints1.route('/addusers/')
def add_users():
    users = []
    for i in range(10):
        users.append(UserModel(name='kunkun' + str(i), age=i))
    try:
        db.session.add_all(users)
        db.session.commit()
    except:
        db.session.rollback()
        db.session.flush()
    return 'OK!'


# 添加电影数据
@blueprints1.route('/addmovie/')
def add_movies():
    movies = []
    for i in range(4):
        movies.append(Movie(name='电影' + str(i)))
    try:
        db.session.add_all(movies)
        db.session.commit()
    except:
        db.session.rollback()
        db.session.flush()
    return 'OK!'


2.添加第三张表的关联关系记录
@blueprints1.route('/addcollect/')
def add_collect():
    # 用户收藏电影
    user = UserModel.query.get(1)
    movie = Movie.query.get(1)
    user.movies.append(movie)
    db.session.commit()
    return 'OK!'


3.修改第三张表的记录
@blueprints1.route('/updatecollect/')
def update_collect():
    # 用户id为2的用户取消收藏电影id为3的电影
    user = UserModel.query.get(2)
    movie = Movie.query.get(3)
    user.movies.remove(movie)
    db.session.commit()
    return 'OK!'


4.删除用户(删除多对多的任意一张表都是一样的)
@blueprints1.route('/deluser/')
def del_user():
    '''
        删除后,第三张表中对应的userid为1的记录会被删除,不会像一对多那样设置为null
    '''
    # 级联删除
    user = UserModel.query.get(1)
    db.session.delete(user)
    db.session.commit()
    return 'OK!'



5.查询(最重要的)
@blueprints1.route('/getcollect/')
def get_collect():
    # 查找某一个用户收藏的所有电影
    user = UserModel.query.get(1)
    # 反向查找 (正反看db.relationship ,db.relationship在的一边为正向,db.relationship在Moive表,所有为反向查找,反向查找backref)
    print(user.movies)  # [<Movie 1>, <Movie 2>, <Movie 3>]

    # 查找收藏了某个电影的所有用户
    movie = Movie.query.get(3)
    print(movie.usermodel)  # 正向查找(关联关系名) ,获得到的是一个查询集对象,在db.relationship中的lazy设置了dynamic,所以movie.usermodel还可以继续使用filter过滤等操作
    # SELECT usermodel.id AS usermodel_id, usermodel.name AS usermodel_name, usermodel.age AS usermodel_age FROM usermodel, collects WHERE ? = collects.movie AND usermodel.id = collects.userid
    print(list(movie.usermodel))
    return 'OK!'
posted @ 2023-07-04 10:22  春游去动物园  阅读(42)  评论(0编辑  收藏  举报