如何使用 make_transient() 复制 SQLAlchemy 映射对象? [英] How to use make_transient() to duplicate an SQLAlchemy mapped object?

查看:30
本文介绍了如何使用 make_transient() 复制 SQLAlchemy 映射对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道如何复制或复制 SQLAlchemy 映射对象的问题被问了很多次.答案始终取决于需求或如何解释重复"或复制".这是问题的专门版本,因为我得到了使用 make_transient() 的提示.

I know the question how to duplicate or copy a SQLAlchemy mapped object was asked a lot of times. The answer always depends on the needs or how "duplicate" or "copy" is interpreted. This is a specialized version of the question because I got the tip to use make_transient() for that.

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

But I have some problems with that. I don't really know how to handle the primary key (PK) here. In my use cases the PK is always autogenerated by SQLA (or the DB in background). But this doesn't happen with a new duplicated object.

代码有点伪.

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()

推荐答案

在创建对象实例transient后,您必须删除它的对象 ID.如果没有对象 ID,您可以再次将其添加到数据库中,这将为它生成一个新的对象 ID.

After making a object instance transient you have to remove its object-id. Without an object-id you can add it again to the database which will generate a new object-id for it.

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()

这篇关于如何使用 make_transient() 复制 SQLAlchemy 映射对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆