使用 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 关系时是不是需要外键的主要内容,如果未能解决你的问题,请参考以下文章