2015-06-26 9 views
6

Il metodo db.create_all() di Flask-SQL Alchemy crea ogni tabella corrispondente ai miei modelli definiti. Non istanzia mai né registro istanze dei modelli. Sono solo definizioni di classe che ereditano da db.Model. Come fa a sapere quali modelli ho definito?In che modo Flask-SQLAlchemy crea_all individua i modelli da creare?

+0

@davidism volevo sapere questo perché non riuscivo a capirne come funzionava. Di solito lavoro con linguaggi di livello inferiore che non beneficiano delle capacità di riflessione di Python. Come tale, sono rimasto perplesso e sfiorare il codice sorgente non ha rivelato nulla di ovvio. Grazie per aver dedicato del tempo a scrivere una spiegazione migliore. –

risposta

11

Flask-SQLAlchemy non fa nulla di speciale, è una parte standard di SQLAlchemy.

La chiamata db.create_all chiama infine db.Model.metadata.create_all. Le tabelle sono associated with a MetaData instance as they are defined. Il meccanismo esatto è molto tortuoso all'interno di SQLAlchemy, dato che c'è molta contabilità dietro le quinte in corso, quindi ho semplificato notevolmente la spiegazione.

db.Model è un declarative base class, che presenta alcuni comportamenti di metaclassi speciali. Quando viene definito, crea internamente un'istanza per memorizzare le tabelle che genera per i modelli. Quando si sottoclasse lo db.Model, il suo comportamento di metacarattere registra la classe in db.Model._decl_class_registry e la tabella in db.Model.metadata.


Le classi vengono definite solo quando vengono importati i moduli che li contengono. Se hai un modulo my_models scritto da qualche parte, ma non viene mai importato, il suo codice non viene mai eseguito in modo che i modelli non vengano mai registrati.

Questo può essere il caso di una certa confusione su come SQLAlchemy rileva che i modelli provengono. Nessun modulo viene "scansionato" per sottoclassi, non viene utilizzato il codice db.Model.__subclasses__, ma l'importazione dei moduli da qualche parte è richiesta per l'esecuzione del codice.

  1. Il modulo contenente i modelli viene importato ed eseguito.
  2. modello viene eseguito definizione di classe, sottoclassi tavolo db.Model
  3. del modello è iscritto su db.Model.metadata
+1

Per essere chiari, stai dicendo che, ad esempio, in uno scenario in cui nessuno dei modelli di classe è effettivamente istanziato in nessuna parte dello script, il modo in cui SQLAlchemy funziona è che tutte le classi che sottoclasse la classe base dichiarativa sono registrate in questa classe registro (ed è per questo che vengono creati quando si chiama il metodo create_all nonostante il fatto che tali classi modello non siano chiamate o istanziate in un punto qualsiasi di uno script)? – SeanJarp

2

È necessario chiamare lo create_all() nello stesso modulo di tutti i modelli. In caso contrario, è necessario importarli. Quindi sqlalchemy passa attraverso tutte le classi in quel modulo e controlla se ereditano da db.model. Se è così, può creare la tabella corrispondente. Anche spiegato here.

+0

Ho trovato il metodo incorporato 'globals()' (https://docs.python.org/3.4/library/functions.html#globals) che elenca tutti i simboli nel modulo corrente. Iterare attraverso il risultato e le classi di filtraggio che ereditano db.Model sembra essere una soluzione piuttosto semplice. –

+0

In realtà non ha bisogno di passare attraverso tutte le classi nel modulo. Se tutti i modelli sono stati importati, db.Model .__ sottoclassi __() fornirà tutte le classi che ereditano da db.Model – TheGeorgeous

+1

Questo è sbagliato. SQLAlchemy non "scansiona" i moduli importati per sottoclassi di 'db.Model', né usa' db.Model .__ subclasses__'. La registrazione tiene il tempo di definizione della classe, db.Model ha un comportamento in metaclasse che registra le classi e le tabelle. – davidism