113 votes

Quand dois-je utiliser sqlalchemy back_populate?

Lorsque j'essaie SQLAlchemy Relation Exemple suivant ce guide: Modèles de relation de base

J'ai ce code

 #!/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)
 

Cela fonctionne bien, mais dans le guide, il est indiqué que le modèle devrait être:

 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")**
 

Pourquoi n'ai-je pas besoin de back_populates ou backref dans mon exemple? Quand devrais-je utiliser l'un ou l'autre?

210voto

Brendan Abel Points 3745

Si vous utilisez backref vous n'avez pas besoin de déclarer la relation sur la seconde table.

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'))

Si vous êtes pas à l'aide de backref, et la définition de l' relationships'séparément, alors si vous n'utilisez pas back_populates, sqlalchemy ne savez pas à connecter les relations, de sorte que la modification de l'un modifie également les autres.

Donc, dans votre exemple, où vous avez défini le relationships'séparément, mais ne procure pas un back_populates argument, la modification d'un champ ne serait pas automatiquement à jour les autres dans votre transaction.

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

Voir comment il n'a pas automatiquement de remplir le children domaine?

Maintenant, si vous fournissez un back_populates argument, sqlalchemy permettra de relier les champs.

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")

Alors maintenant, nous obtenons

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

Sqlalchemy sait que ces deux domaines sont liés, et de mettre à jour les uns que les autres est mise à jour. Il est intéressant de noter que l'utilisation d' backref vont ce faire, trop. À l'aide de back_populates est agréable, si vous souhaitez définir les relations sur chaque classe, de sorte qu'il est facile de voir tous les champs juste en regardant le modèle de la classe, au lieu d'avoir à regarder les autres classes qui définissent des champs via backref.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X