当我按照这篇指南尝试使用SQLAlchemy Relation Example时:Basic Relationship Patterns,我有以下代码。
#!/usr/bin/env python
# encoding: utf-8
from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///:memory:', echo=True)
Session = sessionmaker(bind=engine)
session = Session()
Base = declarative_base(bind=engine)
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
parent = relationship("Parent")
Base.metadata.create_all()
p = Parent()
session.add(p)
session.commit()
c = Child(parent_id=p.id)
session.add(c)
session.commit()
print "children: {}".format(p.children[0].id)
print "parent: {}".format(c.parent.id)
这个功能很好用,但是指南中说模型应该是:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
**children = relationship("Child", back_populates="parent")**
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
**parent = relationship("Parent", back_populates="children")**
为什么我的例子中不需要使用back_populates
或者backref
? 何时应该使用其中一个?
back_populates
和backref
的说明:backref
更加简洁,因为你不需要在两个类中都声明关系,但实际上我认为这并不值得一行的省略。我认为back_populates
更好,不仅因为在 Python 文化中 "显式优于隐式" (Python 之禅),而且当你有许多模型时,通过快速查看其声明,你可以看到所有关系及其名称,而无需查看相关的所有模型。此外,back_populates
的一个好处是,在大多数 IDE 中,你可以自动完成双向关系。 - Fabianoparent_id
是否真的必要?还有,如文档中所示,辅助表又该怎么处理呢?(https://flask-sqlalchemy.palletsprojects.com/en/2.x/models/#many-to-many-relationships) - Luiz Taufferparent_id
是用于存储父子关系的实际外键字段,它是必需的。辅助表用于定义多对多关系(例如,如果一个 Child 可以有多个 Parent)。上述 fkey 示例是经典的一对多示例,其中每个 Child 都有一个且仅有一个 Parent,而一个 Parent 可以有多个 Children。 - Brendan Abelback_populates
时我开始遇到循环依赖问题。因此,在只需要在一个端点使用实体时,使用backref
有助于减少遇到依赖性的可能性。 - omufeed