I have a simple Flask demo app (Python 3) containing some top level app initialisation code, and a blueprint that just sets/unsets some boolean flags. The structure looks like this:
flaskery
├── config.py
├── flaskery
│ ├── app.py - application init code (create app, db)
│ ├── __init__.py - empty
│ ├── __main__.py - entry point
│ └── switches
│ ├── state.py - db structure
│ ├── switches.py - control code
│ └── templates
│ └── (template stuff)
└── setup.py
The app.py
file contains the application initialisation code, including:
app = Flask(__name__)
# Note: Alchy has the same interface as flask.ext.sqlalchemy.SQLAlchemy,
# except that the model is less coupled to flask.
db = Alchy(app, Model=SwitchesState)
# Circular dependency!
from flaskery.switches.switches import switches_app
app.register_blueprint(switches_app)
db.create_all()
However, the blueprint code contains:
from flaskery.app import db
...so that it can do things like, eg.
switches_app = Blueprint('switches', __name__, url_prefix='', template_folder='templates')
@switches_app.route("/")
def root():
# SwitchesState is your run-of-the-mill SQL schema defined as
# a class.
state = SwitchesState()
# Do things that include, say...
db.session.add(state)
db.session.commit()
# etc.
template = render_template(...)
return template
I don't like this circular dependency. I would prefer the blueprint to only need to know about the interface required to manipulate the DB session (if at all), and not need to import already-initialised objects from the top level. Making the top level app code not rely on import order is another goal. I'd also like to avoid relying on a global in control code (although Flask's "session" and "request" globals kind of scuttle that, but less of that would be good).
Is there a way to break this circular dependency and still use Flask?