¿Cuándo necesito usar sqlalchemy back_populated?

Cuando bash SQLAlchemy Relation Ejemplo siguiendo esta guía: Patrones de relación básicos

Tengo este codigo

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

Funciona bien, pero en la guía, dice que el modelo debe ser:

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

¿Por qué no necesito back_populates o backref en mi ejemplo? ¿Cuándo debo usar uno o el otro?

Si usa backref no necesita declarar la relación en la segunda tabla.

 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 no usa backref , y define las relationship por separado, entonces si no usa back_populates , sqlalchemy no sabrá conectar las relaciones, por lo que modificar una también modifica la otra.

Entonces, en su ejemplo, donde definió las relationship por separado, pero no proporcionó un argumento back_populates , la modificación de un campo no actualizaría automáticamente el otro en su transacción.

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

¿Ves cómo no llenó automáticamente el campo de los children ?

Ahora, si proporciona un argumento de back_populates , sqlalchemy conectará los campos.

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

Así que ahora tenemos

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

Sqlalchemy sabe que estos dos campos están relacionados ahora, y los actualizará a medida que se actualice el otro. Vale la pena notar que usar backref también hará esto. El uso de back_populates es agradable si desea definir las relaciones en cada clase, por lo que es fácil ver todos los campos solo mirando la clase modelo, en lugar de tener que mirar otras clases que definen campos a través de backref.