星光不问赶路人,时光|

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!'

本文作者:春游去动物园

本文链接:https://www.cnblogs.com/chunyouqudongwuyuan/p/17525002.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   春游去动物园  阅读(44)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开
  1. 1 生分 川青
生分 - 川青
00:00 / 00:00
An audio error has occurred.

生分 - 川青

词:莎子

曲:邵翼天

编曲:林亦

混音:罗杨轩

吉他:林亦

制作人:谢宇伦

监制:曾炜超/陈显

策划:+7

统筹:黄染染

出品:漫吞吞文化

『酷狗音乐人 • 星曜计划』

全方位推广,见证星力量!

「版权所有未经许可 不得商业翻唱或使用」

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡

有些话一开口会伤人

有些话一开口会伤人

所以我选择默不作声

所以我选择默不作声

爱一个人

若甘愿陪衬

甘愿牺牲

也许换个名分

也不是没可能

我不怕在爱里做个蠢人

我不怕在爱里做个蠢人

也不怕爱过之后再分

也不怕爱过之后再分

爱一个人

有万种身份

万种可能

只是没想到

我们最后友人相称

我们怎么变得那么生分

我们怎么变得那么生分

连说话都要掌握好分寸

怕不注意流言

见缝插针

怕不小心我们

成陌生人

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡

有些话一开口会伤人

有些话一开口会伤人

所以我选择默不作声

所以我选择默不作声

爱一个人

若甘愿陪衬

甘愿牺牲

也许换个名分

也不是没可能

我不怕在爱里做个蠢人

我不怕在爱里做个蠢人

也不怕爱过之后再分

也不怕爱过之后再分

爱一个人

有万种身份

万种可能

只是没想到我们最后

友人相称

我们怎么变得那么生分

连说话都要掌握好分寸

怕不注意流言见缝插针

怕不小心我们成陌生人

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡

我们怎么变得那么生分

我们怎么变得那么生分

连说话都要掌握好分寸

怕不注意流言见缝插针

怕不小心我们成陌生人

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡