2015-05-17 12 views
6

Conosco molte volte la domanda su come duplicare o copiare un oggetto mappato SQLAlchemy. La risposta dipende sempre dalle esigenze o da come "duplicato" o "copia" viene interpretato. Questa è una versione specializzata della domanda perché ho avuto il suggerimento di usare make_transient() per quello.Come utilizzare make_transient() per duplicare un oggetto mappato SQLAlchemy?

Ma ho qualche problema. Non so davvero come gestire la chiave primaria (PK) qui. Nei miei casi d'uso il PK è sempre generato automaticamente da SQLA (o dal DB in background). Ma questo non succede con un nuovo oggetto duplicato.

Il codice è un po 'pseudo.

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

Nessuno ha un'idea? – buhtz

risposta

4
if __name__ == '__main__': 
    obj = GetOneMachineDataFromDatabase() 

    make_transient(obj) 
    obj._oid = None 
    _session.add(obj) 
    # this include a flush() and create a new primary key 
    _session.commit() 
Problemi correlati