我在Flask应用程序中使用了很多werkzeug.local.LocalProxy对象。它们应该是对象的完美替代品,但实际上并非如此,因为它们无法正确响应type()或instanceof()。
SQLAlchemy根本不喜欢它们。如果我对SQLAlchemy记录创建LocalProxy,则SQLAlchemy会将其视为“无”。如果我将LocalProxy传递给一个简单的类型,它只是说这是错误的类型。
Here's an example of Flask-SQLAlchemy having a bad time with LocalProxy。
你们如何处理这个问题?只是经常调用_get_current_object()?如果SQLAlchemy或Flask-SQLAlchemy可以自动更优雅地自动处理这些LocalProxy对象,那就太酷了,特别是考虑到Flask-Login使用它们,并且几乎每个人都使用它们,对吗?
我正在考虑将此功能添加到我的项目中以对其进行处理,并在将它们传递给sqlalchemy之前将其中的任何本地代理包装起来:
from werkzeug.local import LocalProxy
def real(obj):
if isinstance(obj, LocalProxy):
return obj._get_current_object()
return obj
最佳答案
我修补了SQLAlchemy
使用的驱动程序,但我担心它不是最通用的解决方案。
from flask_sqlalchemy import SQLAlchemy as FlaskSQLAlchemy
from sqlalchemy.engine import Engine
from werkzeug.local import LocalProxy
class SQLAlchemy(FlaskSQLAlchemy):
"""Implement or overide extension methods."""
def apply_driver_hacks(self, app, info, options):
"""Called before engine creation."""
# Don't forget to apply hacks defined on parent object.
super(SQLAlchemy, self).apply_driver_hacks(app, info, options)
if info.drivername == 'sqlite':
from sqlite3 import register_adapter
def adapt_proxy(proxy):
"""Get current object and try to adapt it again."""
return proxy._get_current_object()
register_adapter(LocalProxy, adapt_proxy)
elif info.drivername == 'postgresql+psycopg2': # pragma: no cover
from psycopg2.extensions import adapt, register_adapter
def adapt_proxy(proxy):
"""Get current object and try to adapt it again."""
return adapt(proxy._get_current_object())
register_adapter(LocalProxy, adapt_proxy)
elif info.drivername == 'mysql+pymysql': # pragma: no cover
from pymysql import converters
def escape_local_proxy(val, mapping):
"""Get current object and try to adapt it again."""
return converters.escape_item(
val._get_current_object(),
self.engine.dialect.encoding,
mapping=mapping,
)
converters.encoders[LocalProxy] = escape_local_proxy
原始来源可以找到here。
关于python - Flask-SQLAlchemy中的LocalProxy对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26643531/