2016-10-05 2 views
19

Wenn ich versuche, SQLAlchemy Relation Beispiel nach dieser Anleitung: Basic Relationship PatternsWann muss ich sqlalchemy back_populates verwenden?

Ich habe diesen 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) 

Es funktioniert gut, aber in der Führung, sagt es das Modell sein sollte:

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

Warum brauche ich in meinem Beispiel nicht back_populates oder backref? Wann sollte ich das eine oder andere benutzen?

Antwort

37

Wenn Sie backref verwenden, müssen Sie die Beziehung in der zweiten Tabelle nicht deklarieren.

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

Wenn Sie nichtbackref verwenden, und die Definition der relationship ‚separat s, dann, wenn Sie nicht back_populates nicht verwenden, sqlalchemy nicht wissen, die Beziehungen zu verbinden, so dass eine Modifizierung auch modifiziert das andere.

Also, in Ihrem Beispiel, wo Sie die relationship s separat definiert haben, aber kein back_populates Argument zur Verfügung gestellt, würde die Änderung eines Feldes nicht automatisch die andere in Ihrer Transaktion aktualisieren.

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

Sehen Sie, wie es nicht automatisch das children Feld ausfüllen haben?

Jetzt, wenn Sie ein back_populates Argument liefern, wird sqlalchemy die Felder verbinden.

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

So, jetzt bekommen wir

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

sqlalchemy kennt diese beiden Felder jetzt verwandt sind, und werden jeweils als andere aktualisiert wird aktualisiert. Es ist erwähnenswert, dass die Verwendung von backref dies auch tun wird. Verwenden Sie back_populates ist nett, wenn Sie die Beziehungen für jede Klasse definieren möchten, so ist es einfach zu sehen, alle Felder nur Blick auf die Modellklasse, anstatt zu anderen Klassen, die Felder über Backref definieren, zu sehen.

Verwandte Themen