python - 我的 Flask-Admin ModelView 的 __init__ 没有应用程序上下文——它通常什么时候获得一个?

标签 python flask sqlalchemy flask-sqlalchemy flask-admin

我有一个工作示例 Flask-Admin 应用程序 on GitHub它查询 View (本身基于 MySQL 的 information_schema.TABLES)以动态更新 ModelView 的 column_labelscolumn_descriptions 属性。还有一个小的模板修改,用于将工具提示添加到包含来自数据库的列注释的标题行。

我付出了很多努力来解决这个问题,因为在我的 Python 代码中重新键入列描述似乎很愚蠢,因为它们已经使用 COMMENT< 输入到数据库中 创建表时的 SQL 关键字。

在简单的测试应用程序中,一切都按预期工作;我收到了 modelsession 参数给 ModelView__init__ 方法,我使用 session 查询其他模型的列标签/评论,更新 View 上的 self.column_labelsself.column_descriptions,然后调用 super ()

Animated GIF showing column tooltips

然而,在更复杂的应用程序中,我得到了可怕的 RuntimeError: No application found。当我尝试在 ModelView__init__ 方法中查询其他模型时,要么在 View 函数内部工作,要么推送应用程序上下文。我要注意的演示应用程序和我的“真实”应用程序之间的唯一显着区别是我导入了一个在另一个 .py 文件中实例化的 SQLAlchemy 对象,然后调用它的 init_app() 在我的 app.py 中将其连接到 Flask 实例。

编辑:正是问题所在SQLAlchemy 实例以通常的方式创建,在 Flask-SQLAlchemy Quickstart 中演示在他们的 __init__() 中获得一个合适的 Flask 应用程序实例;当我使用 db.init_app(app) 时,我得到了 No application found 错误。

我的问题是:Flask-Admin ModelView 何时开始存在于 Flask 应用程序上下文中? 为什么 import db from something 的情况不同.py; db.init_app(app)db = SQLAlchemy(app)?有什么方法可以跟踪 Flask 应用程序的启动过程并挂接到那个确切的时刻,以便我可以看到这里发生了什么?

这是涉及的两个基本部分(完整源代码 for each 在 GitHub 上,如上所述):

提供“元数据”列的模型,包括评论

# models.py
# [SQLALchemy imports and declaration of 'Base']
class ColumnProperty(Base):
    # this view is based on MySQL's 'information_schema.TABLES'
    __tablename__ = 'v_column_properties'

    parent_table = Column(String(64), primary_key=True)
    name = Column(String(64), primary_key=True)
    # [some fields elided]
    comment = Column(String(1024)) # type: str

实例化时查询上述模型的ModelView

# views.py
from flask_admin.contrib.sqla import ModelView

class TestView(ModelView): 
    def __init__(self, model, session, **kwargs):
        from models import ColumnProperty as cp

        descriptions = {}
        q = session.query(cp).filter(cp.parent_table==model.__tablename__)

        for row in q.all():
            descriptions[row.name] = row.comment

        self.column_descriptions = descriptions 
        super(TestView, self).__init__(model, session, **kwargs)

最佳答案

我会覆盖 ModelViewrender 方法并在那里设置您的 column_descriptions。显然,您可以设置某种缓存机制来减少数据库查询的数量。

类似(完全未经测试)- 注意在查询中使用 self.session:

# views.py
from flask_admin.contrib.sqla import ModelView

class TestView(ModelView):

    def render(self, template, **kwargs):
        from models import ColumnProperty as cp

        descriptions = {}
        q = self.session.query(cp).filter(cp.parent_table==model.__tablename__)

        for row in q.all():
            descriptions[row.name] = row.comment

        self.column_descriptions = descriptions

        super(TestView, self).render(template, **kwargs)

关于python - 我的 Flask-Admin ModelView 的 __init__ 没有应用程序上下文——它通常什么时候获得一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50459142/

相关文章:

javascript - html 在单击按钮时从 json 数据加载更多

python - 在 pandas 中过滤、分组和计数?

python - 使用专门的面向 JSON 的 Flask 应用程序示例时出现属性错误

python - 为什么在 jinja 中使用 "safe"过滤器会创建嵌套元素

python - 如何在 SQLAlchemy 查询中获取列名?

python - 如何知道我的 Python 测试是否在覆盖模式下运行?

python - sqlalchemy:无需密码即可连接到 MySQL

python - 如何在 python Flask 中验证 html 表单?

python - 如何找到 SQLAlchemy 模型的所有混合属性?

python - 可以在没有数据库的情况下评估 sqlalchemy 子句吗?