Get all models from flask-sqlalchemy db
In SQLAlchemy 1.4, the _decl_class_registry.values()
method has removed, you can use db.Model.registry.mappers
instead:
models = {
mapper.class_.__name__: mapper.class_
for mapper in db.Model.registry.mappers
}
See the details in this issue.
There are several related questions, but I didn't see any exact duplicates.
Using your code to get the table names, and this question's accepted answer to get the classes, we can match the classes to the tablenames that are registered on your database.
classes, models, table_names = [], [], []
for clazz in db.Model._decl_class_registry.values():
try:
table_names.append(clazz.__tablename__)
classes.append(clazz)
except:
pass
for table in db.metadata.tables.items():
if table[0] in table_names:
models.append(classes[table_names.index(table[0])])
Where models
is the list of models registed on your database.
The try catch is required because a <sqlalchemy.ext.declarative.clsregistry._ModuleMarker object>
will be included in the for clazz in ...
loop, and it doesn't have a __tablename__
attribute.
If you only need the classes, there is an simpler solution. I came up with it based on Celeo’s answer:
from flask import current_app
# This is to be generic (ie. no need to pass your actual SQLAlchemy instance)
# This way you can include it even in your own extension.
db = current_app.extensions['sqlalchemy'].db
[cls for cls in db.Model._decl_class_registry.values()
if isinstance(cls, type) and issubclass(cls, db.Model)]
This doesn’t need all those extra helper variables, just queries the class registry, and filters out everything that is not a model.