从 flask-sqlalchemy db 获取所有模型

Posted

技术标签:

【中文标题】从 flask-sqlalchemy db 获取所有模型【英文标题】:Get all models from flask-sqlalchemy db 【发布时间】:2014-12-18 08:06:45 【问题描述】:

在 SQLAlchemy 中构建数据库后,我想获取所有模型,即代表它们的类

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

这可以实现吗?怎么样?

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

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

这给出了表格而不是模型本身

【问题讨论】:

【参考方案1】:

有几个相关的问题,但我没有看到任何完全相同的问题。

使用您的代码获取表名,并使用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 是必需的,因为&lt;sqlalchemy.ext.declarative.clsregistry._ModuleMarker object&gt; 将包含在for clazz in ... 循环中,并且它没有__tablename__ 属性。

【讨论】:

【参考方案2】:

如果您只需要类,有一个更简单的解决方案。我是根据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)]

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

【讨论】:

【参考方案3】:

在 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。

【讨论】:

【参考方案4】:

这在我的情况下有效:略短;更具可读性

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

【讨论】:

db_table_creation 是从哪里来的【参考方案5】:

这是我对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__')]

【讨论】:

以上是关于从 flask-sqlalchemy db 获取所有模型的主要内容,如果未能解决你的问题,请参考以下文章

Flask-SQLAlchemy:如何更改表结构?

Flask-SQLAlchemy

Flask-sqlalchemy 语法总结

在 Flask-SQLAlchemy 中查询表的简写

Flask-SqlAlchemy教程增删改查

Flask-Sqlalchemy 使用 postgres 创建视图