Can I avoid circular imports in Flask and SQLAlchemy
Asked Answered
P

2

49

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?).

Punchinello answered 20/3, 2017 at 17:12 Comment(1)
refer this link for a great guide towards creating project structure for flask.Interrogate
P
72

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)
    ...
Phail answered 20/3, 2017 at 17:29 Comment(4)
Great, I think this is exactly what I was looking for. So basically defining these globals in another package gets rid of the need for a circular import? That really cleans up the mess.Punchinello
Exactly. Every object has its place and it's all neatly working together.Phail
It took me an embarrassingly long time to get Flask setup the way I wanted. This helped tremendously. Many thanks.Dock
Guess it's the best practicePeyter
O
31

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    
Otoplasty answered 8/8, 2018 at 5:46 Comment(4)
This answer is more complete in the code example than the accepted one. Crucial addition is that app is defined in the called python file and given the return value of create_app()Halfmoon
But where to write db.create_all().Gaskins
A flask project generator. Based on Flask + SQLAlchemy + marshmallow + webargs. github.com/TTWShell/hobbit-coreOtoplasty
@Gaskins try Flask-Migrate.Otoplasty

© 2022 - 2024 — McMap. All rights reserved.