sqlalchemy hinzufügen Kind in eins-zu-viele-Beziehung
Dies ist das erste mal, das ich verwendet habe, ORM, also ich bin mir nicht sicher, der beste Weg, dies zu behandeln. Ich habe eine eins-zu-viele-Beziehung, wo jeder Elternteil haben viele Kinder:
class Parent(Base):
__tablename__ = 'Parent'
name = Column(String(50))
gid = Column(String(16), primary_key = True)
lastUpdate = Column(DateTime)
def __init__(self,name, gid):
self.name = name
self.gid = gid
self.lastUpdate = datetime.datetime.now()
class Child(Base):
__tablename__ = 'Child'
id = Column(Integer, primary_key = True)
loc = Column(String(50))
status = Column(String(50))
parent_gid = Column(String(16), ForeignKey('Parent.gid'))
parent = relationship("Parent", backref=backref('children'))
Nun, updates kommen über das Netzwerk. Wenn ein update kommt, ich will AKTUALISIEREN Sie die entsprechende Übergeordnete Zeile (Update lastUpdate Spalte) und FÜGEN Sie neue Kinder Zeilen in die Datenbank. Ich weiß nicht, wie zu tun, dass mit ORM. Hier ist mein gescheiterter Versuch:
engine = create_engine('sqlite+pysqlite:///file.db',
module=dbapi2)
Base.metadata.create_all(engine)
session = sessionmaker(bind=engine)()
def addChildren(parent):
p = session.query(Parent).filter(Parent.gid == p1.gid).all()
if len(p) == 0:
session.add(p1)
session.commit()
else:
updateChildren = parent.children[:]
parent.chlidren = []
for c in updateChildren:
c.parent_gid = parent.gid
session.add_all(updateChildren)
session.commit()
if __name__ == '__main__':
#first update from the 'network'
p1 = Parent(name='team1', gid='t1')
p1.children = [Child(loc='x', status='a'), Child(loc='y', status='b')]
addChildren(p1)
import time
time.sleep(1)
#here comes another network update
p1 = Parent(name='team1', gid='t1')
p1.children = [Child(loc='z', status='a'), Child(loc='k', status='b')]
#this fails
addChildren(p1)
Ursprünglich habe ich versucht zu tun, ein Zusammenführen, aber das verursacht das Alter der Kinder zu distanziert mit den Eltern (die ausländischen IDs wurden auf null gesetzt). Was ist der beste Weg, um diesen Ansatz mit ORM? Dank
BEARBEITEN
Ich denke, es macht nicht wirklich Sinn machen, erstellen Sie völlig neue Objekte, wenn updates kommen über das Netzwerk. Ich sollte nur die Abfrage der session, für die entsprechenden übergeordneten, erstellen Sie dann neue Kinder, wenn notwendig, und Zusammenführen? E. g.
def addChildren(pname, pid, cloc, cstat):
p = session.query(Parent).filter(Parent.gid == pid).all()
if len(p) == 0:
p = Parent(pname, pid)
p.children = [Child(loc=cloc, status=cstat)]
session.add(p)
session.commit()
else:
p = p[0]
p.children.append(Child(loc=cloc, status=cstat))
session.merge(p)
session.commit()
InformationsquelleAutor Neal | 2012-01-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Du hast Recht - man sollte nicht den gleichen Eltern zweimal. In Bezug auf das hinzufügen von Kindern, die ... nun, Sie wirklich brauchen nur, um Sie hinzuzufügen und Sie interessieren sich nicht für die bestehenden... Also den bearbeiteten code sollte den job zu erledigen just fine. Sie können es kürzer und besser lesbar, obwohl:
Der Nachteil dieses Weges ist, dass für die bestehenden Eltern-die gesamte Sammlung der Kinder wird in den Arbeitsspeicher geladen werden, bevor ein neues Kind Hinzugefügt und später in der Datenbank gespeichert. Wenn dies der Fall ist (viele und zunehmende Zahl von Kindern, für jeden Elternteil), dann die
faul='noload'
nützlich sein könnten:Dies kann dramatisch verbessern die Geschwindigkeit der Einsätze, aber in diesem Fall ist der Zugriff auf
p.children
wird nie laden Sie die vorhandenen Objekte aus der Datenbank. In solchen Szenarien ist es genug, um eine andere Beziehung. In diesen Situationen, die ich lieber verwenden Gebäude-Query-Enabled-Eigenschaften, so dass Sie am Ende mit einer Eigenschaft nur zum hinzufügen von Objekten, und die andere nur für quering dauerhaft gespeicherten Ergebnisse, die oft benutzt werden, die von verschiedenen teilen des Systems.p.children.extend([list_of_children])
keine?ja, das ist sicher. In der Tat, wenn wir sicher sind, dass die
Parent
existiert für gegebenpid
, und die Aufgabe bei der hand ist nur zum speichern derChild(ren)
, was man tun kann, ist nicht zu laden Beziehung, aber direkt auf den FK-Wert fürparent_gid
:session.add(Child(loc=cloc, status=cstat, parent_gid=pid))
, in dem Fall braucht man nicht einmal zu tricksen die Beziehung zulazy="noload"
, weil der code nicht mit der BeziehungKönntest du bitte auch zeigen, wie man Updates Kind in der gleichen Situation?
InformationsquelleAutor van