2014-10-30 8 views
7

Sto utilizzando molti oggetti werkzeug.local.LocalProxy nell'app Flask. Si suppone che siano degli stand-in perfetti per gli oggetti, ma in realtà non lo sono, dal momento che non rispondono correttamente a type() o instanceof().Oggetti LocalProxy in Flask-SQLAlchemy

SQLAlchemy non gli piace affatto. Se creo un LocalProxy su un record SQLAlchemy, SQLAlchemy lo considera come Nessuno. Se lo passo a un LocalProxy ad un tipo più semplice, si dice semplicemente che è il tipo sbagliato.

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

Come affrontate questo problema con i ragazzi? Basta chiamare _get_current_object() molto? Sarebbe bello se SQLAlchemy o Flask-SQLAlchemy potessero gestire automaticamente questi oggetti LocalProxy in modo più agevole, specialmente considerando che Flask-Login li usa, e praticamente tutti li usano, giusto?

Sto considerando di aggiungere questa funzione per il mio progetto a che fare con esso, e avvolgendo nessuno dei miei localproxies in esso prima di passarli a SQLAlchemy:

from werkzeug.local import LocalProxy 

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

risposta

0

ho applicato la patch al driver utilizzati da SQLAlchemy, ma io temono che non sia la soluzione più generica.

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 

fonte originale si trova here.