当我按照本指南尝试 SQLAlchemy 关系示例时:基本关系模式
我有这个代码
#!/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
? 我什么时候应该使用其中之一?
如果您使用
backref
,则无需在第二个表上声明关系。
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child", backref="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
如果您不使用
backref
,并单独定义relationship
,那么如果您不使用back_populates
,sqlalchemy将不知道如何连接关系,因此修改一个也会修改另一个。
因此,在您的示例中,您单独定义了
relationship
,但没有提供 back_populates
参数,修改一个字段不会自动更新交易中的另一个字段。
>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[]
看看它如何没有自动填写
children
字段?
现在,如果您提供
back_populates
参数,sqlalchemy 将连接字段。
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")
所以现在我们得到了
>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[Child(...)]
Sqlalchemy 知道这两个字段现在是相关的,并且会随着另一个字段的更新而更新。 值得注意的是,使用
backref
也可以做到这一点。 如果您想定义每个类上的关系,那么使用 back_populates
会很好,因此只需浏览模型类就可以轻松查看所有字段,而不必查看通过 backref 定义字段的其他类。