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
Author: Brad Wright, 2012-03-14

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.)

 209
Author: Sean Vieira,
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 /

 19
Author: cybaek,
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