使用 SQLAlchemy 关系时是不是需要外键

Posted

技术标签:

【中文标题】使用 SQLAlchemy 关系时是不是需要外键【英文标题】:Are foreign keys required when using SQLAlchemy relationships使用 SQLAlchemy 关系时是否需要外键 【发布时间】:2020-09-07 02:39:14 【问题描述】:

阅读以下页面,我可以看到我可以使用 orm relationship() 函数设置表之间的关系。

https://docs.sqlalchemy.org/en/13/orm/basic_relationships.html

https://docs.sqlalchemy.org/en/13/orm/backref.html#relationships-backref

使用这个例子:

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    addresses = relationship("Address", backref="user")

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    email = Column(String)
    user_id = Column(Integer, ForeignKey('user.id'))

我是否需要为 Address 类提供明确的 user_id = Column(Integer, ForeignKey('user.id')) 语句?

relationship(backref=...)User 不会提供 Address.user 属性吗?

如果Address 中需要ForeignKey 列,那么为什么User 中不需要它?

【问题讨论】:

相关:***.com/questions/37806625/… 【参考方案1】:

第一: 您在三种情况下使用外键

您对另一个表有一个多键引用。 您要命名外键引用。 您想要添加其他功能,例如级联删除。

第四个原因也是合理的:因为本地编码标准要求使用明确的约束。

第二: 根据SQLAchemy文件

其实relationship.backref关键字就是把only a common shortcut for placing a second relationship()放到Address映射上,包括在which will mirror attribute operations in both directions两边建立一个事件监听器。

但最好使用 back_populates 因为是明确的。 我们显式地向 Address 添加 .user 关系。在这两个关系上,relationship.back_populates directive tells each relationship about the other one, 表明它们应该在彼此之间建立“双向”行为。

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    addresses = relationship("Address", back_populates="user")

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    email = Column(String)
    user_id = Column(Integer, ForeignKey('user.id'))

    user = relationship("User", back_populates="addresses")

【讨论】:

感谢您的回答 Mohammad,但不幸的是它并没有为我解决问题。首先,我选择了 backref 选项,因为它看起来“更容易”,但我很高兴明确地做每一面,所以很清楚正在发生什么。我的主要误解是为什么 User 没有外键,但 Address 有。是因为 (a) 一个电子邮件地址只能适用于一个用户,但一个用户可以有多个电子邮件地址? (b) 我通过关系属性user 引用了用户,那么user_id FK 绝对必要吗?也许我对 python 与 SQL/DB 混淆了? (a) 完全正确。是的,一个电子邮件地址只能适用于一个用户,但一个用户可以有多个电子邮件地址。 (b) 通过数据库处理 FK 但关系属性在 ORM 级别并由 SQLAlchemy 处理 关于 back_populates 与 backref 的说明:backref 更简洁,因为您不需要在两个类上声明关系,但实际上我发现不值得在线保存。我认为 back_populates 更好,不仅因为在 python 文化中“显式优于隐式”(Python 之禅),而且当你有很多模型时,快速浏览它的声明,你可以看到所有关系及其名称,而不是去在所有相关模型中。 同意。最好通过查看类定义来明确可用属性,而不是必须从可能创建它们的其他类中神奇地推断出它们。 致你的“第一个”:它缺少“你想在数据库中强制数据完整性,所以你使用外键约束。 "

以上是关于使用 SQLAlchemy 关系时是不是需要外键的主要内容,如果未能解决你的问题,请参考以下文章

西游之路——python全栈——ORM之SQLAlchemy外键与relationship的关系

SQLAlchemy外键的使用

SQLAlchemy - 不要对关系强制外键约束

SQLAlchemy:表有多个外键约束关系

在 sqlalchemy 中计算子查询

SQLAlchemy ORM 不能使用复合外键