向应用程序工厂注册Flask管理员视图的正确方法 - python

我正在使用应用程序工厂向我的flask应用程序添加视图,如下所示:

(这不是我的实际应用程序工厂,为简洁起见已将其缩短)

def create_app(config_name='default'):
    app = Flask(__name__, template_folder="templates", static_folder='static')
    admin_instance = Admin(app, name='Admin')
    admin_instance.add_view(EntityAdmin(Entity, db.session))

我的EntityAdmin类看起来像这样:

class EntityAdmin(ModelView):
    column_filters = [
        MyCustomFilter(column=None, name='Custom')
    ]

我的自定义过滤器如下所示:

class MyCustomFilter(BaseSQLAFilter):
    def get_options(self, view):
        entities = Entity.query.filter(Entity.active == True).all()
        return [(entity.id, entity.name) for entity in entities]

问题在于,似乎在实例化应用程序时调用了get_options函数,每次调用create_app函数时都会运行一个选择查询。

因此,如果我更新数据库架构并运行flask db migrate命令,则会收到错误消息,因为在运行选择查询时,我添加的新列不存在。该查询引发错误,因为我的数据库架构与实际数据库不同步。

我可以仅在发出实际HTTP请求时注册我的视图吗?如何区分请求和命令?

参考方案

这个过滤器还有一个问题:它的选项是在应用程序实例化时创建的,因此,如果您的实体列表在应用程序运行期间发生了更改,它仍然会返回相同的选项列表。

要解决这两个问题,您无需推迟视图注册。您需要过滤器才能在每次使用时获取选项列表。

问题“在Python中重置生成器对象”的This SO answer描述了一种重用生成器的方法(在您的情况下是数据库查询):

from flask import has_app_context

def get_entities():
    # has_app_context is used to prevent database access
    # when application is not ready yet
    if has_app_context():
        for entity in Entity.query.filter(Entity.active.is_(True)):
            yield entity.id, entity.name

class ReloadingIterator:
    def __init__(self, iterator_factory):
        self.iterator_factory = iterator_factory

    def __iter__(self):
        return self.iterator_factory()

class MyCustomFilter(BaseSQLAFilter):
    def get_options(self, view):
        # This will return a generator which is
        # reloaded every time it is used
        return ReloadingIterator(get_entities)

问题是在请求期间可以多次调用对Entity表的查询。所以我通常使用Flask globals缓存单个请求的结果:

def get_entities():
    if has_app_context():
        if not hasattr(g, 'entities'):
            query = Entity.query.filter(Entity.active.is_(True))
            g.entities = [(entity.id, entity.name) for entity in query]
        for entity_id, entity_name in g.entities:
            yield entity_id, entity_name

flask:异常后停止服务器 - python

我想在发生未处理的异常时立即停止我的Flask服务器。这是一个例子:from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): 1/0 # argh, exception return 'Hello World!' i…

Python GPU资源利用 - python

我有一个Python脚本在某些深度学习模型上运行推理。有什么办法可以找出GPU资源的利用率水平?例如,使用着色器,float16乘法器等。我似乎在网上找不到太多有关这些GPU资源的文档。谢谢! 参考方案 您可以尝试在像Renderdoc这样的GPU分析器中运行pyxthon应用程序。它将分析您的跑步情况。您将能够获得有关已使用资源,已用缓冲区,不同渲染状态上…

Flask-RESTful-返回自定义响应格式 - python

我已经按照以下Flask-RESTful文档定义了自定义响应格式。app = Flask(__name__) api = restful.Api(app) @api.representation('application/octet-stream') def binary(data, code, headers=None): resp =…

Python sqlite3数据库已锁定 - python

我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…

如何在Flask中生成临时下载? - python

我有一个Flask应用,可让用户下载MP3文件。如何使下载的URL仅在特定时间段内有效?例如,我不想让任何人简单地转到example.com/static/sound.mp3并访问文件,而是希望验证每个请求以防止不必要的带宽。我正在使用Apache服务器,但是如果更容易实现,我可能会考虑切换到另一个服务器。另外,我不想使用Flask来提供文件,因为这会通过迫…