Flask-SQLAlchemy\'s db.create_all()
method creates each table corresponding to my defined models. I never instantiate or register instances of the models. They
Flask-SQLAlchemy does nothing special, it's all a standard part of SQLAlchemy.
Calling db.create_all eventually calls db.Model.metadata.create_all. Tables are associated with a MetaData instance as they are defined. The exact mechanism is very circuitous within SQLAlchemy, as there is a lot of behind the scenes bookkeeping going on, so I've greatly simplified the explanation.
db.Model
is a declarative base class, which has some special metaclass behavior. When it is defined, it creates a MetaData
instance internally to store the tables it generates for the models. When you subclass db.Model
, its metaclass behavior records the class in db.Model._decl_class_registry
as well as the table in db.Model.metadata
.
Classes are only defined when the modules containing them are imported. If you have a module my_models
written somewhere, but it is never imported, its code never executes so the models are never registered.
This may be where some confusion about how SQLAlchemy detects the models comes from. No modules are "scanned" for subclasses, db.Model.__subclasses__
is not used, but importing the modules somewhere is required for the code to execute.
db.Model
db.Model.metadata
You need to call create_all()
in the same module as all the models are in. If they are in separate modules, you need to import them all before calling create_all()
. SQLAlchemy looks at what models have been subclassed from db.Model
, and it will only see models that have been imported. It will create the corresponding table for each model. Also explained here.