133 votes

En flacon de SQLAlchemy importation de contexte/question

Je veux structure de ma Gourde app quelque chose comme:

./site.py
./apps/members/__init__.py
./apps/members/models.py

apps.members est un Flacon Plan d'action.

Maintenant, afin de créer les classes du modèle, j'ai besoin d'avoir une emprise de l'application, quelque chose comme:

# apps.members.models
from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy

db = SQLAlchemy(current_app)

class Member(db.Model):
    # fields here
    pass

Mais si j'essaie de l'importer ce modèle dans mon Plan d'application, j'ai le redoutable RuntimeError: working outside of request context. Comment puis-je obtenir une prise de mon application correctement ici? Relative des importations pourrait fonctionner, mais ils sont assez moches, et ont leur propre contexte, des enjeux, de l'e.g:

from ...site import app

# ValueError: Attempted relative import beyond toplevel package

334voto

Sean Vieira Points 47080

L' flaskext.sqlalchemy module ne doit pas être initialisé avec l'app sur le champ, vous pouvez faire ceci à la place:

# apps.members.models
from flaskext.sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Member(db.Model):
    # fields here
    pass

Et puis dans l'installation de votre application, vous pouvez appeler 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 cette façon, vous pouvez éviter cyclique des importations.

Ce modèle ne pas nécessiter la vous placez tous vos modèles dans un seul fichier. Il suffit d'importer le db variable dans chacun de vos modules de modèle.

Exemple

# apps.shared.models
from flaskext.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)

Note: ceci est une esquisse de certains de la puissance que cela vous donne - il est évidemment tout à fait un peu plus que vous pouvez faire pour assurer un développement encore plus facile (à l'aide d'un create_app modèle, l'auto-enregistrement des modèles dans certains dossiers, etc.)

27voto

cybaek Points 86

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

J'ai juste découpé un app.py pour app.py et model.py sans l'aide de Plan d'action. Dans ce cas, la réponse ci-dessus ne marche pas de travail. Une ligne de code est nécessaire pour le travail.

avant:

db.init_app(app)

après:

db.app = app
db.init_app(app)

Et la, le lien suivant est très utile.

http://piotr.banaszkiewicz.org/blog/2012/06/29/flask-sqlalchemy-init_app/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X