• flask 中orm关系映射 sqlalchemy的查询


    flask的orm框架(SQLAlchemy)-一对多查询以及多对多查询

     
    • 一对多,多对多是什么?

    一对多。例如,班级与学生,一个班级对应多个学生,或者多个学生对应一个班级。

    多对多。例如,学生与课程,可以有多个学生修同一门课,同时,一门课也有很多学生。

    • 一对多查询

    如果一个项目,有两张表。分别是班级表,学生表。

    在设计数据表时,我们给学生表设置一个外键,指向班级表的 id 。

    sqlalchemy 模板创建表的代码:

    复制代码
     1 from flask import Flask, render_template, request, flash, redirect
     2 from flask_sqlalchemy import SQLAlchemy
     3 
     4 app = Flask(__name__,static_folder="static",template_folder="templates")
     5 
     6 # 设置数据库连接属性
     7 app.config['SQLALCHEMY_DATABASE_URI'] = '×××'
     8 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
     9 
    10 # 实例化 ORM 操作对象
    11 db = SQLAlchemy(app)
    12 
    13 # 班级表
    14 class Classes(db.Model):
    15     __tablename__ = "classes"
    16     id = db.Column(db.Integer,primary_key=True)
    17     name = db.Column(db.String(20),nullable=False,unique=True)
    18 
    19 # 学生表
    20 class Students(db.Model):
    21     __tablename__ = "students"
    22     id = db.Column(db.Integer,primary_key=True)
    23     name = db.Column(db.String(40),nullable=False)
    24     cls_id = db.Column(db.Integer,db.ForeignKey("classes.id"))    # 注意要写成(表名.字段名)
    复制代码

    创建完表,插入完数据后。

    如果我们知道学生的学号,要查学生班级的名称,应该怎么操作呢?

    现在可以用一种比较麻烦的方达查询:

    cls_id = Students.query.filter(Student.id == 'xxx').first()
    cls = Classes.query.filter(Classes.id == cls.id).first()
    print(cls.name)

    这样的方法太麻烦了,有没有简单的办法?

    上面创建表的代码,在18行可以插入一条语句。

    relate_student = db.relationship("Students",backref='relate_class',lazy='dynamic')
    • 其中realtionship描述了Students和Classes的关系。在此文中,第一个参数为对应参照的类"Students"
    • 第二个参数backref为类Students申明新属性的方法
    • 第三个参数lazy决定了什么时候SQLALchemy从数据库中加载数据
      • 如果设置为子查询方式(subquery),则会在加载完Classes对象后,就立即加载与其关联的对象,这样会让总查询数量减少,但如果返回的条目数量很多,就会比较慢
      • 另外,也可以设置为动态方式(dynamic),这样关联对象会在被使用的时候再进行加载,并且在返回前进行过滤,如果返回的对象数很多,或者未来会变得很多,那最好采用这种方式

    如果一大堆理论看不明白,那么知道怎么用就可以了。

    如果知道学生的姓名,想知道班级的名称,可以这样查:

    stu = Students.query.filter(Students.name == 'xxx').first()
    stu.relate_class.name    # stu.relate_class 会跳到 classes 表

    如果知道班级的名称,想返回全部学生的名字的列表,可以这样查:

    cls = Classes.query.filter(Classes.name == 'xxx').first()
    cls.relate_student.name    # cls.relate_stu 会跳到 students 表

    可以使用这样的方法,有两个要求,第一是要设置外键,第二是这句语句:

    relate_student = db.relationship("Students",backref='relate_class',lazy='dynamic')

    注意,什么时候用 relate_student ,什么时候用 relate_class 。以及 relationship 这条语句的书写,要清楚!

    • 多对多查询

    假设一堆学生选了不同的课程,这就是多对多关系。

    复制代码
    tb_student_course = db.Table('tb_student_course',
                                 db.Column('student_id', db.Integer, db.ForeignKey('students.id')),
                                 db.Column('course_id', db.Integer, db.ForeignKey('courses.id'))
                                 )
    
    
    class Student(db.Model):
        __tablename__ = "students"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
    
       # 关联属性,多对多的情况,可以写在任意一个模型类中 relate_courses = db.relationship('Course', secondary=tb_student_course, backref='relate_student', lazy='dynamic') class Course(db.Model): __tablename__ = "courses" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True)
    复制代码

    添加测试数据:

    复制代码
    # 添加测试数据
    
        stu1 = Student(name='张三')
        stu2 = Student(name='李四')
        stu3 = Student(name='王五')
    
        cou1 = Course(name='物理')
        cou2 = Course(name='化学')
        cou3 = Course(name='生物')
    
        stu1.courses = [cou2, cou3]    # 记得要添加关系
        stu2.courses = [cou2]
        stu3.courses = [cou1, cou2, cou3]
    
        db.session.add_all([stu1, stu2, stu2])
        db.session.add_all([cou1, cou2, cou3])
    
        db.session.commit()
    复制代码

    要查某个学生修的全部课程,修了某个课程的全部学生:

    for course in stu1.relate_courses:
        print(course.name)
    
    for student in cou2.relate_student:
        print(student)
  • 相关阅读:
    2018-2-13-win10-uwp-如何让WebView标识win10手机
    2018-2-13-win10-uwp-如何让WebView标识win10手机
    2018-3-22-win10-uwp-设置-HttpClient-浏览器标识
    2018-3-22-win10-uwp-设置-HttpClient-浏览器标识
    2018-2-13-WPF-获得触笔悬停元素上
    2018-2-13-WPF-获得触笔悬停元素上
    ACM-ICPC 2019 山东省省赛总结
    ACM-ICPC 2019 山东省省赛总结
    ACM-ICPC 2019 山东省省赛D Game on a Graph
    ACM-ICPC 2019 山东省省赛D Game on a Graph
  • 原文地址:https://www.cnblogs.com/liang715200/p/10421296.html
Copyright © 2020-2023  润新知