您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

python – sqlalchemy以一对多的关系添加孩子

5b51 2022/1/14 8:23:32 python 字数 5457 阅读 579 来源 www.jb51.cc/python

这是我第一次使用ORM,所以我不知道最好的方法来处理这个.我有一对多的关系,每个父母可以有很多孩子: class Parent(Base): __tablename__ = 'Parent' name = Column(String(50)) gid = Column(String(16), primary_key = True) lastUpdate = Col

概述

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列)并将新的子项行插入数据库.我不知道如何使用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',Child(loc='k',status='b')]
    #this fails
    addChildren(p1)

我最初试图做一个合并,但这导致老的孩子被取消与父母的关联(外部ID被设置为null).用ORM来处理这个问题的最好方法是什么?谢谢

编辑

我想,当更新进入网络时,创建全新的对象并不真正有意义.我应该只是查询相应的父级会话,然后在必要的时候创建新的子项并合并?例如.

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()
def addChildren(pname,cstat):
    p = session.query(Parent).get(pid) # will give you either Parent or None
    if not(p):
        p = Parent(pname,pid)
        session.add(p)
    p.children.append(Child(loc=cloc,status=cstat))
    session.commit()

这种方式的缺点是,对于现有的Parent,在添加新的Child并将其保存到数据库之前,所有的Children集合将被加载到内存中.如果是这种情况(每个父母的孩子数量越来越多),那么lazy='noload'可能是有用的:

parent = relationship("Parent",backref=backref('children',lazy='noload'))

这可能会显着提高插入速度,但在这种情况下,对p.children的访问将永远不会从数据库加载现有对象.在这种情况下,定义另一种关系就足够了.在这种情况下,我更喜欢使用Building Query-Enabled Properties,所以最终只能添加一个属性添加对象,另一个属性仅用于查询持久化结果,这些结果通常由系统的不同部分使用.

总结

以上是编程之家为你收集整理的python – sqlalchemy以一对多的关系添加孩子全部内容,希望文章能够帮你解决python – sqlalchemy以一对多的关系添加孩子所遇到的程序开发问题。


如果您也喜欢它,动动您的小指点个赞吧

除非注明,文章均由 laddyq.com 整理发布,欢迎转载。

转载请注明:
链接:http://laddyq.com
来源:laddyq.com
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


联系我
置顶