2014-10-30 40 views
7

我在Flask應用程序中使用了很多werkzeug.local.LocalProxy對象。它們應該是對象的完美替身,但它們並不是真正的,因爲它們不能正確地響應type()或instanceof()。Flask-SQLAlchemy中的LocalProxy對象

SQLAlchemy根本不喜歡它們。如果我將LocalProxy創建爲SQLAlchemy記錄,則SQLAlchemy將其視爲None。如果我將LocalProxy傳遞給一個更簡單的類型,它只是說它是錯誤的類型。

Here's an example of Flask-SQLAlchemy having a bad time with LocalProxy

你們如何處理這個問題?只需調用_get_current_object()很多?如果SQLAlchemy或Flask-SQLAlchemy可以更自然地自動處理這些LocalProxy對象,特別是考慮Flask-Login使用它們,幾乎每個人都使用它,對嗎?

我正在考慮加入這個功能,我的項目來處理它,並通過他們的SQLAlchemy包之前任我在它localproxies的:

from werkzeug.local import LocalProxy 

def real(obj): 
    if isinstance(obj, LocalProxy): 
     return obj._get_current_object() 
    return obj 

回答

0

我修補由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