I want to structure my Flask app something like:
./site.py ./apps/members/__init__.py ./apps/members/models.py
apps.members is a Flask Blueprint.
Now, in order to create the model classes I need to have a hold of the app, something like:
# apps.members.models from flask import current_app from flaskext.sqlalchemy import SQLAlchemy db = SQLAlchemy(current_app) class Member(db.Model): # fields here pass
But if I try and import that model into my Blueprint app, I get the dreaded
RuntimeError: working outside of request context. How can I get a hold of my app correctly here? Relative imports might work but they're pretty ugly and have their own context issues, e.g:
from ...site import app # ValueError: Attempted relative import beyond toplevel package
flask_sqlalchemy module does not have to be initialized with the app right away - you can do this instead:
# apps.members.models from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class Member(db.Model): # fields here pass
And then in your application setup you can call
# apps.application.py from flask import Flask from apps.members.models import db app = Flask(__name__) # later on db.init_app(app)
This way you can avoid cyclical imports.
This pattern does not necessitate the you place all of your models in one file. Simply import the
db variable into each of your model modules.
# 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)
Note: this is a sketch of some of the power this gives you - there is obviously quite a bit more that you can do to make development even easier (using a
create_app pattern, auto-registering blueprints in certain folders, etc.)
an 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()
I just splitted one app.py to app.py and model.py without using Blueprint. In that case, the above answer dosen't work. A line code is needed to work.
db.app = app db.init_app(app)
And, the following link is very useful.