gpt4 book ai didi

python - 使用应用程序工厂模式将应用程序上下文传递给自定义转换器

转载 作者:太空宇宙 更新时间:2023-11-03 11:25:55 26 4
gpt4 key购买 nike

我目前正在构建一个使用 Application Factory 的应用程序图案。在此应用程序中,我有一个自定义 URL 转换器,它接受一个整数并返回具有该 ID 的 SQLAlchemy 模型实例(如果存在)。当我不使用应用程序工厂模式时这工作正常,但是有了它,我在访问任何使用转换器的路由时收到此错误:

RuntimeError: application not registered on db instance and no application bound to current context

我的应用程序结构如下所示:

app/__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config

db = SQLAlchemy()

def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)

from app.converters import CustomConverter
app.url_map.converters["custom"] = CustomConverter

from app.views.main import main
app.register_blueprint(main)
return app

app/converters.py

from werkzeug.routing import ValidationError, IntegerConverter
from app.models import SomeModel


class CustomConverter(IntegerConverter):
""" Converts a valid SomeModel ID into a SomeModel object. """
def to_python(self, value):
some_model = SomeModel.query.get(value)
if some_model is None:
raise ValidationError()
else:
return some_model

app/views/main.py

from flask import Blueprint

main = Blueprint("main", __name__)

# This causes the aforementioned error.
@main.route("/<custom:some_model>")
def get_some_model(some_model):
return some_model.name

有没有办法以某种方式将应用程序上下文传递给 CustomConverter?我尝试用 with current_app.app_context() 包装 to_python 方法的内容,但所做的只是将错误减少到 RuntimeError: working outside of application上下文

这是完整的回溯:

File "c:\Python34\lib\site-packages\flask\app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "c:\Python34\lib\site-packages\flask\app.py", line 1812, in wsgi_app
ctx = self.request_context(environ)
File "c:\Python34\lib\site-packages\flask\app.py", line 1773, in request_context
return RequestContext(self, environ)
File "c:\Python34\lib\site-packages\flask\ctx.py", line 247, in __init__
self.match_request()
File "c:\Python34\lib\site-packages\flask\ctx.py", line 286, in match_request
self.url_adapter.match(return_rule=True)
File "c:\Python34\lib\site-packages\werkzeug\routing.py", line 1440, in match
rv = rule.match(path)
File "c:\Python34\lib\site-packages\werkzeug\routing.py", line 715, in match
value = self._converters[name].to_python(value)
File "c:\Users\Encrylize\Desktop\Testing\Flask\app\converters.py", line 8, in to_python
some_model = SomeModel.query.get(value)
File "c:\Python34\lib\site-packages\flask_sqlalchemy\__init__.py", line 428, in __get__
return type.query_class(mapper, session=self.sa.session())
File "c:\Python34\lib\site-packages\sqlalchemy\orm\scoping.py", line 71, in __call__
return self.registry()
File "c:\Python34\lib\site-packages\sqlalchemy\util\_collections.py", line 988, in __call__
return self.registry.setdefault(key, self.createfunc())
File "c:\Python34\lib\site-packages\flask_sqlalchemy\__init__.py", line 136, in __init__
self.app = db.get_app()
File "c:\Python34\lib\site-packages\flask_sqlalchemy\__init__.py", line 809, in get_app
raise RuntimeError('application not registered on db '
RuntimeError: application not registered on db instance and no application bound to current context

最佳答案

我刚刚遇到了同样的问题。我不确定解决它的“正确”方法是什么,因为这似乎是一件相当明显的事情并且应该可以正常工作,但我使用适用于应用程序工厂模式的大多数问题的通用解决方法解决了它: 将 app 对象保存在一个闭包中,并从外部注入(inject)它。对于您的示例:

def converters(app):
class CustomConverter(IntegerConverter):
""" Converts a valid SomeModel ID into a SomeModel object. """
def to_python(self, value):
with app.app_context():
some_model = SomeModel.query.get(value)
if some_model is None:
raise ValidationError()
else:
return some_model
return {"custom": CustomConverter}

def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
db.init_app(app)

app.url_map.converters.update(converters(app))

from app.views.main import main
app.register_blueprint(main)
return app

显然,这不是那么优雅或理想:在 URL 解析期间创建临时应用程序上下文,然后立即丢弃。

编辑: 主要问题:这对非平凡的情况有效。返回的对象不会连接到实时 session (临时应用程序上下文关闭时会清除 session )。修改和延迟加载会中断。

关于python - 使用应用程序工厂模式将应用程序上下文传递给自定义转换器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33856007/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com