从flask-sqlalchemy db获取所有模型

时间:2014-10-22 18:46:09

标签: flask sqlalchemy flask-sqlalchemy

在SQLAlchemy中构建数据库之后,我想获得所有模型,也就是说,代表它们的类

>>> db
<SQLAlchemy engine='postgresql:///example'>
>>> ???
[<db.Model 'User'>, <db.Model 'Comment'>, <db.Model 'Article'>]

这可以实现吗?怎么样?

我可以很好地得到表格,而不是模型。例如:

>>> for t in db.metadata.tables.items():
        print(t)

这使得表格不是模型本身

5 个答案:

答案 0 :(得分:10)

有几个相关的问题,但我没有看到任何确切的重复。

使用您的代码获取表名,以及this question获得类的接受答案,我们可以将这些类与数据库中注册的表名匹配。

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])])

models是数据库中注册的模型列表。

try catch是必需的,因为<sqlalchemy.ext.declarative.clsregistry._ModuleMarker object>循环中会包含for clazz in ...,并且它没有__tablename__属性。

答案 1 :(得分:7)

如果您只需要这些课程,则可以使用更简单的解决方案。我根据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)]

这不需要所有这些额外的辅助变量,只需查询类注册表,并过滤掉所有非模型的内容。

答案 2 :(得分:2)

在 SQLAlchemy 1.4 中,_decl_class_registry.values() 方法已删除,您可以使用 db.Model.registry.mappers 代替:

models = {
    mapper.class_.__name__: mapper.class_
    for mapper in db.Model.registry.mappers
}

查看this issue中的详细信息。

答案 3 :(得分:0)

这适用于我的情况:略短;更具可读性

models = []
for name, thing in db_table_creation.__dict__.iteritems():
    if isinstance(thing, sqlalchemy.ext.declarative.DeclarativeMeta) and hasattr(thing, '__tablename__'):
        models.append(thing)

答案 4 :(得分:0)

这是我的Celeo’s answer的变体,其中包含打字和简洁的中介步骤:

from ??? import db  # Import from wherever you have this, or use GergelyPolonkai's method to get a db object.
from typing import List, Dict, Union
from flask_sqlalchemy import DefaultMeta
from sqlalchemy.ext.declarative.clsregistry import _ModuleMarker

registered_classes: List[Union[DefaultMeta, _ModuleMarker]] = \
    [x for x in db.Model._decl_class_registry.values()]
registered_models: List[DefaultMeta] = \
    [x for x in registered_classes if isinstance(x, DefaultMeta)]
tables: List[DefaultMeta] = \
    [x for x in registered_models if hasattr(x, '__tablename__')]