2012-03-26 7 views
5

Ho una classe tavolo SQLAlchemy creato utilizzando il metodo dichiarativa:Come aggiungere automaticamente un oggetto SQLAlchemy alla sessione?

mysqlengine = create_engine(dsn) 
session = scoped_session(sessionmaker(bind=mysqlengine)) 
Base = declarative_base() 
Base.metadata.bind = mysqlengine 

class MyTable(Base): 
    __table_args__ = {'autoload' : True} 

Ora, quando si utilizza questa tabella all'interno del codice Vorrei non dover utilizzare il session.add metodo al fine di aggiungere ogni nuovo record per la sessione attiva così invece di:

row = MyTable(1, 2, 3) 
session.add(row) 
session.commit() 

mi piacerebbe avere:

row = MyTable(1, 2, 3) 
session.commit() 

Ora, so che questa domanda già: Possible to add an object to SQLAlchemy session without explicit session.add()?

E, mi rendo conto che è possibile forzare questo comportamento nel modo seguente:

class MyTable(Base): 
    def __init__(self, *args, **kw): 
    super(MyTable, self).__init__(*args, **kw) 
    session.add(self) 

Tuttavia, io non voglio gonfiare il mio codice che contiene 30 tabelle con questo metodo. So anche che Elixir (http://elixir.ematia.de/trac/wiki) fa questo, quindi deve essere possibile in un certo senso.

risposta

15

Super semplice. Utilizza un evento:

from sqlalchemy import event, Integer, Column, String 
from sqlalchemy.orm import scoped_session, sessionmaker, mapper 
from sqlalchemy.ext.declarative import declarative_base 

Session = scoped_session(sessionmaker()) 

@event.listens_for(mapper, 'init') 
def auto_add(target, args, kwargs): 
    Session.add(target) 

Base = declarative_base() 

class A(Base): 
    __tablename__ = "a" 

    id = Column(Integer, primary_key=True) 
    data = Column(String) 

a1 = A(data="foo") 
assert a1 in Session() 
+1

Ricorda che se stai utilizzando la convalida SQLAlchemy o gli eventi di pre-flush, devi anche eliminare dalla sessione un oggetto che fallisce la convalida. Ho appena ottenuto un po 'di quello quando uso questa soluzione. –

Problemi correlati