Flask-Problema de importación / contexto de SQLAlchemy
Quiero estructurar mi aplicación Flask algo como:
./site.py
./apps/members/__init__.py
./apps/members/models.py
apps.members
es un plano de Frasco.
Ahora, para crear las clases modelo necesito tener un control de la aplicación, algo así como:
# apps.members.models
from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(current_app)
class Member(db.Model):
# fields here
pass
Pero si intento importar ese modelo a mi aplicación Blueprint, obtengo el temido RuntimeError: working outside of request context
. ¿Cómo puedo obtener una bodega de mi aplicación correctamente aquí? Las importaciones relativas pueden funcionar, pero son bastante feas y tienen sus propios problemas de contexto, por ejemplo:
from ...site import app
# ValueError: Attempted relative import beyond toplevel package
2 answers
El módulo flask_sqlalchemy
no tiene que inicializarse con la aplicación de inmediato - puede hacer esto en su lugar:
# apps.members.models
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Member(db.Model):
# fields here
pass
Y luego en la configuración de su aplicación puede llamar a init_app
:
# apps.application.py
from flask import Flask
from apps.members.models import db
app = Flask(__name__)
# later on
db.init_app(app)
De esta manera se pueden evitar las importaciones cíclicas.
Este patrón hace no que usted coloque todos sus modelos en un archivo. Simplemente importa la variable db
en cada uno de tus modelos módulos.
Ejemplo
# apps.shared.models
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
# apps.members.models
from apps.shared.models import db
class Member(db.Model):
# TODO: Implement this.
pass
# apps.reporting.members
from flask import render_template
from apps.members.models import Member
def report_on_members():
# TODO: Actually use arguments
members = Member.filter(1==1).all()
return render_template("report.html", members=members)
# apps.reporting.routes
from flask import Blueprint
from apps.reporting.members import report_on_members
reporting = Blueprint("reporting", __name__)
reporting.route("/member-report", methods=["GET","POST"])(report_on_members)
# apps.application
from flask import Flask
from apps.shared import db
from apps.reporting.routes import reporting
app = Flask(__name__)
db.init_app(app)
app.register_blueprint(reporting)
Nota: este es un bosquejo de parte del poder que esto le da - obviamente hay un poco más que puede hacer para hacer el desarrollo aún más fácil (usando un patrón create_app
, auto-registro de blueprints en ciertas carpetas, etc.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-24 00:19:11
Un original app.py: http://pythonhosted.org/Flask-SQLAlchemy/quickstart.html#quickstart
...
app = flask.Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = flask.ext.sqlalchemy.SQLAlchemy(app)
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
...
class Computer(db.Model):
id = db.Column(db.Integer, primary_key=True)
...
# Create the database tables.
db.create_all()
...
# start the flask loop
app.run()
Acabo de dividir uno app.py to app.py y model.py sin usar Blueprint. En ese caso, la respuesta anterior no funciona. Se necesita un código de línea para funcionar.
Antes :
db.init_app(app)
Después de :
db.app = app
db.init_app(app)
Y, el siguiente enlace es muy utilidad.
Http://piotr.banaszkiewicz.org/blog/2012/06/29/flask-sqlalchemy-init_app /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-08 00:46:56