2011-04-25 14 views
5

Digamos que tengo una parte de mi aplicación Flask que quiero extraer y usar en múltiples proyectos diferentes. Tiene modelos SQLAlchemy que usan Flask-SQLAlchemy, así como vistas y plantillas. Puedo obtener los decoradores de aplicaciones usando un Módulo, pero ¿cómo puedo manejar el objeto DB de SQLAlchemy?¿Cómo se hace un componente reutilizable con Flask-SQLAlchemy?

Como mi componente necesita estar separado, no puedo simplemente importar el objeto db. Pero no creo que deba crear el objeto db dos veces. ¿Cómo mezclaría sus metadatos con los metadatos en el resto del proyecto?

Respuesta

3

Al principio debe compartir metadata y no usar el db.Model de frasco-sqlalchemy como base para su aplicación reutilizable.

En segundo lugar, debe volver a crear todas las clases extendiéndoles nuevas bases de flask-sqlalchemy para soportar señales, atajos y otras cosas.

Integrar bases (puede ser con errores):

def integrate_models(cls, nbase): 
     new_bases = list(cls.__bases__) + [nbase] 
     new_dict = dict(cls.__dict__) 
     new_dict.update(dict(nbase.__dict__)) 
     return type.__new__(cls.__class__, cls.__name__, tuple(new_bases), new_dict) 

Ejemplo Flask aplicación con extensión sqlalchemy:

# -*- coding: utf-8 -*- 
from flask import Flask 
from flaskext.sqlalchemy import SQLAlchemy 

app = Flask(__name__) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' 
db = SQLAlchemy(app) 

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 
    email = db.Column(db.String(120), unique=True) 

    def __init__(self, username, email): 
     self.username = username 
     self.email = email 

    def __repr__(self): 
     return '<User %r>' % self.username 

if __name__ == '__main__': 
     from some_model_base import init_metadata 
     init_metadata(db.Model.metadata) 

     from some_model import SomeClass 

     SomeClass = integrate_models(SomeClass, db.Model) 

     db.create_all() 

     print SomeClass.query.all() 

Dónde some_model_base.py:

from sqlalchemy.ext.declarative import declarative_base 
Base = declarative_base() 

def init_metadata(metadata): 
    Base.metadata = metadata 

Y some_model.py :

from sqlalchemy import Column, Integer, String 
from some_model_base import Base 

class SomeClass(Base): 
    __tablename__ = 'some_table' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(50)) 

En este ejemplo, solo se probaron los accesos directos db.create_all y SomeClass.query.

Lo siento por mi pobre inglés.

+0

Hm, tendré que probar esto. ¿Puedes encontrar una forma de configurar los modelos en el otro módulo para tener una relación con los modelos en el programa principal? –

+0

Creo que la mejor forma de hacerlo es declarar en sus clases base de aplicaciones reutilizables o MixIns y luego crear modelos concretos subclasándolos. – estin

1

Debe usar flask.current_app, es un objeto proxy para acceder a la aplicación actual, y es lo que se usa en algunas extensiones. Por lo tanto, el código sería algo como esto:

from flask import current_app 
from flaskext.sqlalchemy import SQLAlchemy 

db = SQLAlchemy(current_app) 

y luego usar su objeto db como lo haría normalmente. Pero no estoy seguro de si esto funcionaría si el usuario utilizara su módulo y también necesitara usar flaskext.sqlalchemy, tal vez entraría en conflicto, le sugiero probar esto, para asegurarse de que su módulo sea 100% compatible con cualquier aplicación flask .

Cuestiones relacionadas