如何使用make_transient()复制SQLAlchemy映射对象?

发布于 2021-01-29 16:06:12

我知道很多人问过如何复制或复制SQLAlchemy映射对象的问题。答案总是取决于需求或如何解释“重复”或“副本”。这是该问题的专门版本,因为我有使用的技巧make_transient()

但是我有一些问题。我真的不知道如何在这里处理主键(PK)。在我的用例中,PK始终由SQLA(或后台DB)自动生成。但这不会发生在新的重复对象上。

该代码有点伪。

import sqlalchemy as sa
from sqlalchemy.orm.session import make_transient

_engine = sa.create_engine('postgres://...')
_session = sao.sessionmaker(bind=_engine)()


class MachineData(_Base):
    __tablename__ = 'Machine'    
    _oid = sa.Column('oid', sa.Integer, primary_key=True)


class TUnitData(_Base):
    __tablename__ = 'TUnit'
    _oid = sa.Column('oid', sa.Integer, primary_key=True)
    _machine_fk = sa.Column('machine', sa.Integer, sa.ForeignKey('Machine.oid'))
    _machine = sao.relationship("MachineData")

    def __str__(self):
        return '{}.{}: oid={}(hasIdentity={}) machine={}(fk={})' \
        .format(type(self), id(self),
                self._oid, has_identity(self),
                self._machine, self._machine_fk)


if __name__ == '__main__':
    # any query resulting in one persistent object
    obj = GetOneMachineDataFromDatabase()

    # there is a valid 'oid', has_identity == True
    print(obj)

    # should i call expunge() first?

    # remove the association with any session
    # and remove its “identity key”
    make_transient(obj)

    # 'oid' is still there but has_identity == False
    print(obj)

    # THIS causes an error because the 'oid' still exsits
    # and is not new auto-generated (what should happen in my
    # understandings)
    _session.add(obj)
    _session.commit()
关注者
0
被浏览
156
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    使对象实例成为 瞬态之后, 您必须 删除 其对象ID。如果没有对象标识,则可以将其再次添加到数据库中,数据库将为其生成新的对象标识。

    if __name__ == '__main__':
        # the persistent object with an identiy in the database
        obj = GetOneMachineDataFromDatabase()
    
        # make it transient
        make_transient(obj)
        # remove the identiy / object-id
        obj._oid = None
        # adding the object again generates a new identiy / object-id
        _session.add(obj)
        # this include a flush() and create a new primary key
        _session.commit()
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看