Comparta modelos de sqlalchemy entre el matraz y otras aplicaciones

Tengo una aplicación Flask en ejecución que se configura de acuerdo con una combinación de las mejores prácticas que encontramos en línea y en el libro "Flask Web Development" de Miguel Grinberg.

Ahora necesitamos una segunda aplicación Python, que NO es una aplicación web, y que necesita acceso a los mismos modelos que la aplicación Flask. Queríamos reutilizar los mismos modelos de curso, por lo que ambas aplicaciones pueden beneficiarse del código compartido.

Hemos eliminado las dependencias de la extensión matraz-sqlalchemy (que utilizamos antes, cuando teníamos solo la aplicación Flask). Y lo reemplazó con elExtensión declarativa SQLalchemy descrita aquí, que es un poco más simple (Flask-SQLalchemy agrega algunas cosas específicas a la SQLAlchemy estándar)

En línea con el ejemplo, hemos creado un archivo database.py en la raíz. En nuestro caso, hay dos cosas diferentes del ejemplo de extensión declarativa: puse el motor y la sesión en una clase, porque todos nuestros modelos usan db.session, en lugar de db_session, y le paso un diccionario con valores de configuración a la claseen eso(), para poder reutilizar esta database.py tanto de Flask como de otra aplicación, usando una configuración diferente. se parece a esto:

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base


class Database(object):

    def __init__(self, cfg):
        self.engine = create_engine(cfg['SQLALCHEMY_DATABASE_URI'], convert_unicode=True)
        self.session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=self.engine))

    class Model(object):
        pass

Base = declarative_base()

Así que ahora llegamos al problema real. Flask crea un objeto similar a un diccionario que contiene opciones de configuración y las agrega como una propiedad a la instancia de la aplicación. Los carga de uncarpeta de instancia, unaconfig.py en la raíz del sitio y de las variables de entorno. Necesito pasar el diccionario de configuración de Flask, por lo que necesito Flask para PRIMERO cargar y ensamblar la configuración, y después de eso inicializar la base de datos, y tener un objeto db (configurado) en la raíz del archivo de la aplicación. Sin embargo, seguimos elPatrón de aplicación de fábrica, por lo que podemos usar diferentes configuraciones para diferentes situaciones (prueba, producción, desarrollo).

Esto significa nuestroapp/__init__.py se parece a esto (simplificado):

from flask import Flask
from database import Database
from flask.ext.mail import Mail
from flask_bcrypt import Bcrypt
from config import config

mail = Mail()
bcrypt = Bcrypt()


def create_app(config_name):

    app = Flask(__name__, instance_relative_config=True)

    if not config_name:
        config_name = 'default'
    app.config.from_object(config[config_name])
    app.config.from_pyfile('config.py')
    config[config_name].init_app(app)

    db = Database(app.config)

    mail.init_app(app)
    bcrypt.init_app(app)

    @app.teardown_appcontext
    def shutdown_session(exception=None):
        db.session.remove()

    from main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    return app

Pero la base de datos (desde la que importan los modelos ...) ahora debe estar dentro de la función create_app (), porque ahí es donde Flask carga la configuración. Si creara una instancia del objeto db fuera de la función create_app (), será importable desde los modelos, ¡pero no está configurado!

un modelo de ejemplo tiene este aspecto y, como puede ver, espera un "db" en la raíz de la aplicación:

from . base_models import areas
from sqlalchemy.orm import relationship, backref
from ..utils.helper_functions import newid
from .. import db


class Areas(db.Model, areas):
    """Area model class.
    """
    country = relationship("Countries", backref=backref('areas'))

    def __init__(self, *args, **kwargs):
        self.area_id = newid()
        super(Areas, self).__init__(*args, **kwargs)

    def __str__(self):
        return u"{}".format(self.area_name).encode('utf8')

    def __repr__(self):
        return u"<Area: '{}'>".format(self.area_name).encode('utf8')

Entonces, mi pregunta es, ¿cómo puedo tener una instancia de db que se pueda configurar externamente (ya sea mediante Flask u otra aplicación), y aún usar el patrón Factory de aplicación?

editar: El código de ejemplo era incorrecto, tenía una importación para Flask-SQLalchemy que fue reemplazada porfrom database import Database. Perdón por cualquier confusión.

Respuestas a la pregunta(4)

Su respuesta a la pregunta