2015-06-26 9 views
6

Metoda Flask-SQLAlchemy's db.create_all() tworzy każdą tabelę odpowiadającą moim zdefiniowanym modelom. Nigdy nie stwórz instancji modeli ani nie rejestruj ich. To tylko definicje klas, które dziedziczą po db.Model. Skąd wiadomo, które modele zdefiniowałem?W jaki sposób Flask-SQLAlchemy create_all odkrywa modele do utworzenia?

+0

@davidism chciałem o tym wiedzieć, bo nie mogłem undestand jak to działało. Zwykle pracuję z językami niższego poziomu, które nie korzystają z możliwości refleksyjnych Pythona. W związku z tym byłem zaskoczony i przeglądanie kodu źródłowego nie ujawniło niczego oczywistego. Dziękuję za poświęcenie czasu na napisanie lepszego wyjaśnienia. –

Odpowiedz

11

Flask-SQLAlchemy nie robi nic specjalnego, to wszystko jest standardową częścią SQLAlchemy.

Wywołanie db.create_all ostatecznie wywołuje db.Model.metadata.create_all. Tabele są associated with a MetaData instance as they are defined. Dokładny mechanizm jest bardzo skomplikowany w ramach SQLAlchemy, ponieważ prowadzi się wiele księgowań zza kulis, więc znacznie uprościłem wyjaśnienie.

db.Model to declarative base class, który ma pewne specjalne zachowanie metaclass. Po zdefiniowaniu tworzy wewnętrznie instancję MetaData, aby przechowywać wygenerowane tabele dla modeli. Podczas podklasy db.Model zachowanie jej metaclass zapisuje klasę w db.Model._decl_class_registry, a także w tabeli w db.Model.metadata.


Klasy są definiowane tylko wtedy, gdy moduły je zawierające zostaną zaimportowane. Jeśli masz gdzieś napisany moduł my_models, ale nigdy nie jest on importowany, jego kod nigdy nie jest wykonywany, więc modele nigdy nie są rejestrowane.

Może to być przyczyną pewnych nieporozumień dotyczących sposobu, w jaki SQLAlchemy wykrywa modele. Żadne moduły nie są "skanowane" dla podklas, db.Model.__subclasses__ nie jest używany, ale importowanie modułów gdzieś wymaga wymaganego do wykonania kodu.

  1. Moduł zawierający modele jest importowany i wykonywany.
  2. model definicja klasy jest wykonywany, podklasy tabeli db.Model
  3. modelki jest zarejestrowany db.Model.metadata
+1

Dla jasności mówimy, że na przykład w scenariuszu, w którym żaden z modeli klas nie jest faktycznie tworzony w dowolnym miejscu skryptu, sposób działania SQLAlchemy polega na tym, że wszystkie klasy, które mają podklasę deklaratywnej klasy bazowej, są zapisywane w tej klasie rejestru (i dlatego są tworzone po wywołaniu metody create_all pomimo faktu, że te klasy modeli nie są wywoływane ani tworzone w dowolnym miejscu w skrypcie)? – SeanJarp

2

Musisz zadzwonić pod numer create_all() w tym samym module, w którym znajdują się wszystkie modele. Jeśli tak nie jest, musisz je zaimportować. Następnie sqlalchemy przechodzi przez wszystkie klasy w tym module i sprawdza, czy dziedziczą one z db.model. Jeśli tak, może utworzyć tabelę korespondencyjną. Wyjaśniono również here.

+0

Znalazłem metodę wbudowaną 'globals()' (https://docs.python.org/3.4/library/functions.html#globals), która zawiera listę wszystkich symboli w bieżącym module. Iterowanie poprzez klasy wyników i filtrowania, które dziedziczą db.Model wydaje się dość prostym rozwiązaniem. –

+0

Właściwie to nie musi przechodzić przez wszystkie klasy w module. Jeśli wszystkie modele zostały zaimportowane, klasa db.Model .__ podklas __() poda wszystkie klasy dziedziczące z db.Model – TheGeorgeous

+1

Jest to niepoprawne. SQLAlchemy nie "skanuje" zaimportowanych modułów dla podklas 'db.Model', ani nie używa podklas" db.Model .__ ". Przechowywanie rekordów odbywa się w czasie definiowania klasy, db.Model ma zachowanie metaclass, które rejestruje klasy i tabele. – davidism

Powiązane problemy