SQLalchemy relationship之lazy属性 学习笔记

relationship里面的lazy属性看得头昏脑涨,还是自己来动手弄点数据熟悉一下


模型还是建立在目前在看的Flask Web这本书上面的数据库,方便测试


第一步,建立一对多关系的测试,class是一这一端,对应student是多那一端,意思是,同一个课程,可以有很多学生选这门课

class Student(db.Model):
    __tablename__ = 'students'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    class_id = db.Column(db.Integer, db.ForeignKey('classes.id'))
    def __repr__(self):
        return '<Student: %r>' %self.name

class Class(db.Model):
    __tablename__ = 'classes'
    id = db.Column(db.Integer, primary_key=True)
    students = db.relationship('Student', backref='_class', lazy="select")
    name = db.Column(db.String(64))
    def __repr__(self):
        return '<Class: %r>' %self.name
注意Class里面的students是relationship,里面的lazy我选择了select,也就是默认值


手动插入数据进数据库,注意Allen和Tina选择的是同一门课,class1.

import sqlite3

conn = sqlite3.connect("e:\\flasky1\data-dev.sqlite")

cur = conn.cursor()

cur.execute("insert into students values(1,'Allen',1)")
cur.execute("insert into students values(2,'Bob',2)")
cur.execute("insert into students values(3,'Tina',1)")

cur.execute("insert into classes values(1,'class1')")
cur.execute("insert into classes values(2,'class2')")

cur.close()
conn.commit()
conn.close()

用c1代表第一门课程,class1,然后通过他的students属性,可以看到有多少学生选了这门课

可以看到,当Class的lazy属性是select的时候,他就是直接查找出了对象,并由对象为元素组成了一个list

然后,用s1这个实例对象,通过Class里面的backref=_class属性,也能访问Class内容,因为backref=_class默认也是select属性,所以,他也是直接导出结果




下面我改成dynamic

### SQLAlchemy 中 `relationship` 的使用与问题排查 SQLAlchemy 提供了强大的 ORM 功能,其中 `relationship()` 是用于定义模型之间关联的核心工具。它支持一对一、一对多和多对多关系,并能够自动处理底层数据库的连接逻辑。 #### 一对一关系的实现方式 在定义一对一关系时,需设置 `uselist=False` 参数以确保返回的是单个对象而非列表。这种配置常见于用户与其资料信息之间的映射: ```python class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) profile = relationship("Profile", uselist=False, back_populates="user") ``` 对应的 `Profile` 模型中也应包含反向引用: ```python class Profile(Base): __tablename__ = 'profiles' id = Column(Integer, primary_key=True) user_id = Column(Integer, ForeignKey('users.id')) user = relationship("User", back_populates="profile") ``` 通过这种方式,每个 `User` 实例仅能关联一个 `Profile` 对象[^2]。 #### 一对多关系的典型用法 一对多关系是数据库中最常见的类型之一,通常表现为一个父对象可以拥有多个子对象。例如,一个用户可以发布多篇文章: ```python class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String) articles = relationship("Article", backref="author") ``` 而在 `Article` 模型中,需要明确指定外键字段指向用户的主键: ```python class Article(Base): __tablename__ = 'articles' id = Column(Integer, primary_key=True) title = Column(String) user_id = Column(Integer, ForeignKey('users.id')) ``` 此时可以通过 `user.articles` 获取该用户的所有文章,也可以通过 `article.author` 获得对应的文章作者信息[^2]。 #### 多对多关系的配置方法 多对多关系要求引入中间表来存储两个实体之间的连接信息。例如,学生可以选择多个课程,而每门课程也可被多名学生选修: ```python registrations = Table('registrations', Base.metadata, Column('student_id', Integer, ForeignKey('students.id')), Column('class_id', Integer, ForeignKey('classes.id')) ) class Student(Base): __tablename__ = 'students' id = Column(Integer, primary_key=True) name = Column(String(64)) classes = relationship("Class", secondary=registrations, back_populates="students") ``` 同时,在 `Class` 模型中也需要定义相同的中间表及双向关系: ```python class Class(Base): __tablename__ = 'classes' id = Column(Integer, primary_key=True) name = Column(String(64)) students = relationship("Student", secondary=registrations, back_populates="classes") ``` 这样即可实现双方都能访问对方集合的功能,如 `student.classes` 和 `class.students`[^3]。 #### 加载策略的选择与优化 `relationship` 支持多种加载行为,其中 `lazy` 参数决定了何时以及如何从数据库中获取相关数据。常见的选项包括: - `'select'`:默认值,延迟加载,只有当访问属性时才会执行 SQL 查询。 - `'joined'`:使用 JOIN 一次性获取主表和相关表的数据,适用于频繁访问相关对象的情况。 - `'subquery'`:类似于 `joined`,但使用子查询来加载相关对象。 - `'dynamic'`:返回可进一步过滤的查询对象,适合大数据集或需要分页的场景[^4]。 例如,将 `Class.students` 设置为动态加载模式允许开发者进行更复杂的筛选操作: ```python students = relationship("Student", secondary=registrations, back_populates="classes", lazy="dynamic") ``` 这使得可以在调用 `class.students.filter(...)` 时构建更精细的查询条件。 #### 反向引用的自动化管理 利用 `backref` 或 `back_populates` 可以自动创建双向的关系属性,从而简化代码结构并减少冗余定义。例如,在用户地址关系中: ```python class User(Base): __tablename__ = 'users' id = Column(Integer, primary_key=True) addresses = relationship("Address", backref="user") ``` 此时 `Address` 类会自动生成一个名为 `user` 的属性,指向其所属的 `User` 实例: ```python class Address(Base): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) email = Column(String) user_id = Column(Integer, ForeignKey('users.id')) ``` 这一机制有助于提高开发效率并保持模型间的一致性[^3]。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值