2013-01-31 12 views
18

Voglio duplicare un'istanza di modello (riga) in SQLAlchemy utilizzando l'orm. Il mio primo pensiero è stato quello di fare questo:SQLAlchemy: modifica dell'oggetto distaccato

i = session.query(Model) 
session.expunge(i) 

old_id = i.id 
i.id = None 
session.add(i) 
session.flush() 
print i.id #New ID 

Tuttavia, a quanto pare l'oggetto staccato ancora "ricorda" che cosa id che aveva, anche se ho impostato l'id Nessuno mentre era staccato. Pertanto, session.flush() tenta di eseguire un UPDATE modificando la chiave primaria su null.

È questo comportamento previsto? Come posso rimuovere la 'memoria' di questo attributo e trattare l'oggetto staccato come un nuovo oggetto dopo averlo aggiunto nuovamente alla sessione? In che modo, in generale, si clona un'istanza del modello SQLAlchemy?

risposta

34

questo caso è disponibile utilizzando la funzione di supporto make_transient():

inst = session.query(Model).first() 
session.expunge(inst) 

make_transient(inst) 
inst.id = None 
session.add(inst) 
session.flush() 
print inst.id #New ID 
+0

Grazie, non ho visto che nella documentazione. –

+4

Qual è il modo corretto di copiare anche le relazioni, @zzzeek? – jmagnusson

+0

Anch'io sono interessato a qualcosa di simile. Sono interessato a clonare un'entità (una riga), insieme a tutte le sue entità "figlio" (righe in altre tabelle, con chiavi esterne che puntano a questa riga) e allegare questa nuova riga duplicata ei suoi figli duplicati a una nuova entità padre tramite una chiave esterna diversa nella nuova riga duplicata (ma senza influenzare l'entità esistente e le sue entità figlio). Riesco a vedere questa risposta parziale su un'altra domanda su SO: http://stackoverflow.com/questions/20112850/sqlalchemy-clone-table-row-with-relations?lq=1 – Soferio

1
def duplicate(self): 
    arguments = dict() 
    for name, column in self.__mapper__.columns.items(): 
     if not (column.primary_key or column.unique): 
      arguments[name] = getattr(self, name) 
    return self.__class__(**arguments) 
+0

Se il tuo oggetto è in attesa, questo non lo fa Non ci sono relazioni. Cioè le colonne chiave esterna non sono ancora state compilate. – gromgull

+0

Inoltre non copia i metodi e gli attributi ibridi. – Jakobovski