我什么时候需要使用 sqlchemy back_popates?

当我尝试 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_populatesbackref在我的例子? 什么时候我应该使用其中之一或其他?

60671 次浏览

如果使用 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,sql 炼金术将不知道如何连接这些关系,因此修改一个关系也会修改另一个关系。

因此,在您的示例中,您分别定义了 relationship,但是没有提供 back_populates参数,因此修改一个字段不会自动更新事务中的另一个字段。

>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print(parent.children)
[]

看到它没有自动填写 children字段了吗?

现在,如果提供一个 back_populates参数,sql伟力将连接这些字段。

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(...)]

现在 Sql 炼金术知道这两个字段是相关的,并且会随着其他字段的更新而相互更新。值得注意的是,使用 backref也可以做到这一点。如果您想要定义每个类上的关系,使用 back_populates是很好的,所以很容易看到所有的字段只是瞥一眼模型类,而不必查看通过 backref 定义字段的其他类。