Questa è la prima volta che uso ORM, quindi non sono sicuro che sia il modo migliore per gestirlo. Ho una relazione uno-a-molti, dove ogni genitore può avere molti bambini:sqlalchemy aggiungi figlio nella relazione uno a molti
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'))
Ora, gli aggiornamenti sono venuta in attraverso la rete. Quando arriva un aggiornamento, voglio AGGIORNARE la riga Parent appropriata (aggiornando la colonna lastUpdate) e INSERIRE le nuove righe figli nel database. Non so come farlo con ORM. Qui è il mio tentativo fallito:
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)
Inizialmente ho provato a fare una fusione, ma che ha causato i vecchi bambini di essere dissociati con il genitore (gli ID stranieri sono stati fissati a null). Qual è il modo migliore per avvicinarsi a questo con ORM? Grazie
EDIT
Credo che in realtà non ha senso per creare oggetti del tutto nuovi quando gli aggiornamenti sono disponibili in rete. Dovrei semplicemente interrogare la sessione per il genitore appropriato, quindi creare nuovi figli se necessario e unire? Per esempio.
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()
Per aggiungere un elenco di bambini è possibile utilizzare "p.children.extend ([list_of_children])", no? – aganders3
sì, certo. Infatti, se siamo sicuri che il 'Parent' esiste per il dato' pid', e l'attività in corso è solo per memorizzare 'Child (ren)', ciò che si può fare non è caricare la relazione, ma impostare direttamente il Valore FK per 'parent_gid':' session.add (Child (loc = cloc, status = cstat, parent_gid = pid)) ', nel qual caso non è nemmeno necessario ingannare la relazione con' lazy = "noload" ', perché il codice non utilizzerà la relazione – van
Puoi anche mostrare come aggiornare il bambino nello stesso scenario? –