SQLAlchemy dichiarativa sintassi con autoload (riflessione) in Piloni
-
13-10-2019 - |
Domanda
Vorrei utilizzare caricamento automatico di utilizzare un database existings. Io so come farlo senza sintassi dichiarativa (modello / _ init _ py.):
def init_model(engine):
"""Call me before using any of the tables or classes in the model"""
t_events = Table('events', Base.metadata, schema='events', autoload=True, autoload_with=engine)
orm.mapper(Event, t_events)
Session.configure(bind=engine)
class Event(object):
pass
Questo funziona bene, ma vorrei usare la sintassi dichiarativa:
class Event(Base):
__tablename__ = 'events'
__table_args__ = {'schema': 'events', 'autoload': True}
Purtroppo, in questo modo ottengo:
sqlalchemy.exc.UnboundExecutionError: Nessun motore è legato ai metadati di questa tabella. Passare un motore per la tabella tramite autoload_with =
, o associare i metadati con un motore tramite metadata.bind =
Il problema qui è che non so dove trovare il motore da (per usarlo in autoload_with) in fase di importazione del modello (è disponibile in init_model ()). Ho provato ad aggiungere
meta.Base.metadata.bind(engine)
per environment.py, ma non funziona. Chiunque ha trovato qualche soluzione elegante?
Soluzione
OK, credo di aver capito. La soluzione è dichiarare gli oggetti del modello al di fuori del model/__init__.py
. Ho concluso che __init__.py
viene importato come il primo file durante l'importazione qualcosa da un modulo (in questo caso model
) e questo causa problemi, perché gli oggetti del modello vengono dichiarati prima init_model()
è chiamato.
Per evitare questo ho creato un nuovo file nel modulo model
, per esempio objects.py
. Ho poi dichiarato tutti i miei oggetti del modello (come Event
) in questo file.
Poi, posso importare i miei modelli in questo modo:
from PRJ.model.objects import Event
Inoltre, per evitare di specificare autoload-with
per ogni tabella, ho inserito questa riga alla fine del init_model()
:
Base.metadata.bind = engine
In questo modo posso dichiarare il mio modello di oggetti senza codice standard, in questo modo:
class Event(Base):
__tablename__ = 'events'
__table_args__ = {'schema': 'events', 'autoload': True}
event_identifiers = relationship(EventIdentifier)
def __repr__(self):
return "<Event(%s)>" % self.id
Altri suggerimenti
Ho appena provato questo modulo ORM utilizzando.
Base = declarative_base(bind=engine)
Base.metadata.reflect(bind=engine)
Accesso tabelle manualmente o attraverso l'anello o qualsiasi altra cosa:
Base.metadata.sorted_tables
potrebbe essere utile.
Controlla la Utilizzando SQLAlchemy con piloni esercitazione su come associare i metadati al motore nella funzione init_model
.
Se l'istruzione meta.Base.metadata.bind(engine)
si lega con successo i metadati del modello al motore, si dovrebbe essere in grado di eseguire questa inizializzazione la propria funzione init_model
. Credo che non volevi saltare vincolante i metadati in questa funzione, vero?