Это первый раз, когда я использовал ORM, поэтому я не уверен, что лучший способ справиться с этим. У меня есть отношения один-ко-многим, где каждый родитель может иметь много детей:sqlalchemy add child in one-to-many relationship
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'))
Теперь, обновления приходят через сеть. Когда приходит обновление, я хочу ОБНОВИТЬ соответствующую родительскую строку (обновление столбца LastUpdate) и INSERT новых дочерних строк в базу данных. Я не знаю, как это сделать с ORM. Вот моя неудачная попытка:
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)
Первоначально я пытался сделать слияние, но это вызвало старые дети будут диссоциирует с родителем (иностранные идентификаторы были установлены в нуль). Каков наилучший способ приблизиться к ORM? Благодаря
EDIT
Я предполагаю, что это на самом деле не имеет смысла создавать совершенно новые объекты, когда обновления приходят через сеть. Я должен просто запросить сеанс для соответствующего родителя, а затем создать новые дети, если необходимо, и слить? Например.
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()
Чтобы добавить список детей, вы можете использовать 'p.children.extend ([list_of_children])', no? – aganders3
Да, конечно. На самом деле, если мы уверены, что для данного 'pid' существует' Parent', а задача состоит только в том, чтобы хранить «Child (ren)», то что можно сделать, это не загружать отношения, а напрямую устанавливать Значение FK для 'parent_gid':' session.add (Child (loc = cloc, status = cstat, parent_gid = pid)) ', и в этом случае даже не нужно обманывать связь с' lazy = "noload" ', потому что код не будет использовать связь – van
Не могли бы вы также показать, как обновить ребенка в том же сценарии? –