Fábricas de aplicaciones¶
Si ya estás usando paquetes y blueprints para tu aplicación (Aplicaciones modulares con Blueprints) hay un par de formas muy buenas de mejorar la experiencia. Un patrón común es crear el objeto de la aplicación cuando se importa el blueprint. Pero si mueves la creación de este objeto a una función, puedes crear múltiples instancias de esta aplicación más tarde.
Entonces, ¿por qué querrías hacer esto?
Pruebas. Puedes tener instancias de la aplicación con diferentes configuraciones para probar cada caso.
Múltiples instancias. Imagina que quieres ejecutar diferentes versiones de la misma aplicación. Por supuesto, usted podría tener múltiples instancias con diferentes configuraciones establecidas en su servidor web, pero si usted utiliza las fábricas, puede tener múltiples instancias de la misma aplicación que se ejecuta en el mismo proceso de aplicación que puede ser útil.
Entonces, ¿cómo se implementa esto?
Fábricas básicas¶
La idea es configurar la aplicación en una función. Así:
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
from yourapplication.model import db
db.init_app(app)
from yourapplication.views.admin import admin
from yourapplication.views.frontend import frontend
app.register_blueprint(admin)
app.register_blueprint(frontend)
return app
El inconveniente es que no se puede utilizar el objeto de aplicación en los blueprints en el momento de la importación. Sin embargo, puede utilizarlo desde una solicitud. ¿Cómo se accede a la aplicación con la configuración? Utiliza current_app
:
from flask import current_app, Blueprint, render_template
admin = Blueprint('admin', __name__, url_prefix='/admin')
@admin.route('/')
def index():
return render_template(current_app.config['INDEX_TEMPLATE'])
Aquí buscamos el nombre de una plantilla en la configuración.
Fábricas y extensiones¶
Es preferible crear tus extensiones y fábricas de aplicaciones de manera que el objeto de la extensión no se vincule inicialmente a la aplicación.
Usando Flask-SQLAlchemy, como ejemplo, no deberías hacer algo parecido a esto:
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
db = SQLAlchemy(app)
Pero, más bien, en model.py (o equivalente):
db = SQLAlchemy()
y en su aplicacion.py (o equivalente):
def create_app(config_filename):
app = Flask(__name__)
app.config.from_pyfile(config_filename)
from yourapplication.model import db
db.init_app(app)
Utilizando este patrón de diseño, no se almacena ningún estado específico de la aplicación en el objeto de extensión, por lo que un objeto de extensión puede ser utilizado para múltiples aplicaciones. Para más información sobre el diseño de las extensiones, consulte Desarrollo de extensiones de Flask.
Uso de aplicaciones¶
Para ejecutar una aplicación de este tipo, puede utilizar el comando flask:
$ flask --app hello run
Flask detectará automáticamente la fábrica si se llama create_app
o make_app
en hello
. También puedes pasar argumentos a la fábrica así:
$ flask --app hello:create_app(local_auth=True) run
Entonces se llama a la fábrica create_app
en myapp
con el argumento clave local_auth=True
. Consulta Interfaz de línea de comandos para más detalles.
Mejoras en la fábrica¶
La función de fábrica anterior no es muy inteligente, pero se puede mejorar. Los siguientes cambios son sencillos de implementar:
Hacer posible pasar valores de configuración para las pruebas unitarias para no tener que crear archivos de configuración en el sistema de archivos.
Llamar a una función desde un blueprint cuando la aplicación se está configurando para tener un lugar donde modificar los atributos de la aplicación (como enganchar los manejadores de peticiones antes/después, etc.)
Añadir middlewares WSGI cuando la aplicación se está creando si es necesario.