Колба - SQLAlchemy импорт / проблема контекста
Я хочу структурировать свою колбу приложение что-то вроде:
./site.py
./apps/members/__init__.py
./apps/members/models.py
apps.members
это колба чертеж.
теперь, чтобы создать классы моделей, мне нужно иметь доступ к приложению, что-то вроде:
# apps.members.models
from flask import current_app
from flaskext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(current_app)
class Member(db.Model):
# fields here
pass
но если я попытаюсь импортировать эту модель в мое приложение Blueprint, я получу страшный RuntimeError: working outside of request context
. Как я могу получить доступ к моему приложению правильно здесь? Относительный импорт может работать, но они довольно уродливы и имеют свои собственные проблемы контекста, например:
from ...site import app
# ValueError: Attempted relative import beyond toplevel package
2 ответа:
The
flask_sqlalchemy
модуль не должен быть инициализирован с приложение прямо сейчас - вы можете сделать это:# apps.members.models from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class Member(db.Model): # fields here pass
а потом в настройках приложения вы можете позвонить
init_app
:# apps.application.py from flask import Flask from apps.members.models import db app = Flask(__name__) # later on db.init_app(app)
таким образом, вы можете избежать циклического импорта.
этот шаблон делает не необходимо разместить все ваши модели в одном файле. Просто импортируйте
db
переменная в каждой из вашей модели модули.пример
# 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)
Примечание: это эскиз какой власти это дает вам - там, очевидно, совсем немного больше, что вы можете сделать, чтобы сделать развитие еще проще (с помощью
create_app
шаблон, автоматическая регистрация чертежей в определенных папках и т. д.)
оригинал 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()
Я только что разделил один app.py к app.py и model.py без использования чертежа. В этом случае приведенный выше ответ не работает. Код нужен для работы.
до:
db.init_app(app)
после:
db.app = app db.init_app(app)
и, следующая ссылка очень полезный.
http://piotr.banaszkiewicz.org/blog/2012/06/29/flask-sqlalchemy-init_app/