2015-06-26 3 views
6

Die Methode db.create_all() von Flask-SQLAlchemy erstellt jede Tabelle, die meinen definierten Modellen entspricht. Ich instanziiere oder registriere niemals Instanzen der Modelle. Sie sind nur Klassendefinitionen, die von db.Model erben. Woher weiß es, welche Modelle ich definiert habe?Wie erkennt Flask-SQLAlchemy create_all die zu erstellenden Modelle?

+0

@davidism ich das wissen wollte, registriert ist, weil ich nicht undestand konnte, wie es funktioniert. Ich arbeite normalerweise mit Sprachen auf niedrigerer Ebene, die von den Reflektionsfähigkeiten von Python nicht profitieren. Als solches war ich verwirrt und der Quellcode zu überfliegen ergab nichts Offensichtliches. Danke, dass Sie sich die Zeit genommen haben, eine bessere Erklärung zu schreiben. –

Antwort

11

Flask-SQLAlchemy macht nichts besonderes, es ist alles ein Standard Teil von SQLAlchemy.

Aufruf db.create_all schließlich ruft db.Model.metadata.create_all. Tabellen sind associated with a MetaData instance as they are defined. Der genaue Mechanismus ist innerhalb von SQLAlchemy sehr umständlich, da es eine Menge hinter den Kulissen Buchführung gibt, also habe ich die Erklärung sehr vereinfacht.

db.Model ist eine , die einige spezielle metaclass Verhalten hat. Wenn es definiert ist, erstellt es intern eine MetaData Instanz, um die Tabellen zu speichern, die es für die Modelle generiert. Wenn Sie die Klasse db.Model ableiten, zeichnet das Metaklassenverhalten die Klasse in db.Model._decl_class_registry sowie die Tabelle in db.Model.metadata auf.


Klassen werden nur definiert, wenn die Module, die sie enthalten, importiert werden. Wenn Sie ein Modul my_models irgendwo geschrieben haben, aber es wird nie importiert, wird sein Code nie ausgeführt, damit die Modelle nie registriert werden.

Dies kann sein, wo einige Verwirrung darüber, wie SQLAlchemy die Modelle erkennt, kommt. Keine Module werden für Unterklassen "gescannt", db.Model.__subclasses__ wird nicht verwendet, aber das Importieren der Module irgendwo ist erforderlich für die Ausführung des Codes.

  1. Module mit Modellen werden importiert und ausgeführt.
  2. Modellklassendefinition ausgeführt wird, Unterklassen db.Model
  3. Modells Tisch mit db.Model.metadata
+1

Um es klar zu stellen: In einem Szenario, in dem keines der Klassenmodelle tatsächlich irgendwo im Skript instanziiert wird, funktioniert SQLAlchemy so, dass alle Klassen, die die deklarative Basisklasse ableiten, in dieser Klasse aufgezeichnet werden Registrierung (und deshalb werden sie erstellt, wenn Sie die create_all-Methode aufrufen, obwohl diese Modellklassen nirgendwo in einem Skript aufgerufen oder instanziiert werden)? – SeanJarp

2

Sie müssen create_all() im selben Modul aufrufen, in dem sich alle Modelle befinden. Wenn dies nicht der Fall ist, müssen Sie sie importieren. Dann durchläuft sqlalchemy alle Klassen in diesem Modul und prüft, ob sie von db.model erben. Ist dies der Fall, kann die entsprechende Tabelle erstellt werden. Auch erklärt here.

+0

Ich fand die integrierte Methode 'globals()' (https://docs.python.org/3.4/library/functions.html#globals), die alle Symbole im aktuellen Modul auflistet. Das Durchlaufen der Ergebnis- und Filterklassen, die db.Model erben, scheint eine ziemlich einfache Lösung zu sein. –

+0

Eigentlich muss es nicht alle Klassen im Modul durchlaufen. Wenn alle Modelle importiert wurden, erhalten Sie mit db.Model .__ subclasses __() alle Klassen, die von db.Model erben. – TheGeorgeous

+1

Das ist falsch. SQLAlchemy "überprüft" keine importierten Module für Unterklassen von "db.Model" und auch nicht "db.Model .__ subclasses__". Die Protokollierung erfolgt zur Klassendefinitionszeit, db.Model hat Metaklassenverhalten, das die Klassen und Tabellen aufzeichnet. – davidism

Verwandte Themen