python - tutorial - sqlalchemy documentation
Flask-SQLAlchemy problema de importaciĆ³n/contexto (2)
El módulo flask_sqlalchemy
no tiene que inicializarse con la aplicación de inmediato; puede hacerlo 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 forma puede evitar las importaciones cíclicas.
Este patrón no requiere que coloque todos sus modelos en un solo archivo. Simplemente importe la variable db
en cada uno de sus módulos modelo.
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 boceto de parte de la potencia que esto le brinda; obviamente, hay mucho más que puede hacer para facilitar aún más el desarrollo (utilizando un patrón create_app
, create_app
de planos en ciertas carpetas, etc.)
Quiero estructurar mi aplicación Flask algo así como:
./site.py
./apps/members/__init__.py
./apps/members/models.py
apps.members
es un modelo de matraz.
Ahora, para crear las clases modelo, necesito tener una 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 en mi aplicación Blueprint, obtengo el temido RuntimeError: working outside of request context
. ¿Cómo puedo obtener 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
una aplicación original.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 una app.py en 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 trabajar.
antes :
db.init_app(app)
después :
db.app = app
db.init_app(app)
Y, el siguiente enlace es muy útil.
http://piotr.banaszkiewicz.org/blog/2012/06/29/flask-sqlalchemy-init_app/