Can I avoid circular imports in Flask and SQLAlchemy
Question:
app/init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__ name __)
db = SQLAlchemy(app)
from app import views, models
app/models.py:
from app import db # I want to avoid this everywhere
I really don’t like my submodules having a dependency on their parent. Also can the global package variables be avoided too? I want a more OO solution.
One alternative for app is to use Blueprints I think, but then I loose the route decorator. Also the same cannot be done for db with SQLAlchemy (or can it?).
Answers:
Take a look at this project: https://github.com/sloria/cookiecutter-flask
It’s a great example for doing things the right way. Many of great Flask features are used: blueprints, application factories and more.
Here is how they register extensions, such as SQLAlchemy Database:
# app/extensions.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
...
# app/app.py
from app.extensions import db
def create_app(config_object=ProdConfig):
app = Flask(__name__.split('.')[0])
app.config.from_object(config_object)
register_extensions(app)
...
def register_extensions(app):
db.init_app(app)
...
Try use 3rd. We create exts.py file to instancing SQLAlchemy like this:
exts.py
from flask_sqlalchemy import SQLAlchemy
from flask_xxx import xxx
db = SQLAlchemy()
...
run.py
from flask import Flask
from .exts import db, ...
def register_extensions(app):
db.init_app(app)
...
def create_app(config):
app = Flask(__ name __)
app.config.from_object(config)
register_extensions(app)
return app
app = create_app(config)
models.py
from .exts import db
class XXXModel(db.Model):
pass
app/init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__ name __)
db = SQLAlchemy(app)
from app import views, models
app/models.py:
from app import db # I want to avoid this everywhere
I really don’t like my submodules having a dependency on their parent. Also can the global package variables be avoided too? I want a more OO solution.
One alternative for app is to use Blueprints I think, but then I loose the route decorator. Also the same cannot be done for db with SQLAlchemy (or can it?).
Take a look at this project: https://github.com/sloria/cookiecutter-flask
It’s a great example for doing things the right way. Many of great Flask features are used: blueprints, application factories and more.
Here is how they register extensions, such as SQLAlchemy Database:
# app/extensions.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
...
# app/app.py
from app.extensions import db
def create_app(config_object=ProdConfig):
app = Flask(__name__.split('.')[0])
app.config.from_object(config_object)
register_extensions(app)
...
def register_extensions(app):
db.init_app(app)
...
Try use 3rd. We create exts.py file to instancing SQLAlchemy like this:
exts.py
from flask_sqlalchemy import SQLAlchemy
from flask_xxx import xxx
db = SQLAlchemy()
...
run.py
from flask import Flask
from .exts import db, ...
def register_extensions(app):
db.init_app(app)
...
def create_app(config):
app = Flask(__ name __)
app.config.from_object(config)
register_extensions(app)
return app
app = create_app(config)
models.py
from .exts import db
class XXXModel(db.Model):
pass