什么时候需要使用 sqlalchemy back_populates?

2023-11-22

当我按照本指南尝试 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 or 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'))

如果你是not using backref,并定义relationship是分开的,那么如果你不使用back_populates,sqlalchemy 不会知道如何连接关系,因此修改一个关系也会修改另一个关系。

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

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

看看它如何没有自动填写children field?

现在,如果您提供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 定义字段的其他类。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么时候需要使用 sqlalchemy back_populates? 的相关文章

随机推荐