Home > Back-end >  How to separate flask files when two files depend on each other?
How to separate flask files when two files depend on each other?

Time:11-23

I'm trying to develop a database driven flask app. I have an api.py file which has the flask app, api and SQLAlchemy db objects and a users.py file which contains the routes ands code to create a database table.

In the users.py file, there's a UserManager Resource which has the routes. I have to add this resource to the API from this file.

So users.py needs to import the db and the api from the api.py file and api.py needs to serve the flask app so it has all the variables users.py needs, but api.py also needs to import users.py in order to use it as a flask blueprint.

api.py:

...
from user import user

app = Flask(__name__)
app.register_blueprint(user)
api = Api(app)
...
db = SQLAlchemy(app)
ma = Marshmallow(app)
...
if __name__ == '__main__':
    app.run(debug=True)

users.py:

from api import api

user = Blueprint('user', __name__, template_folder='templates')

db = SQLAlchemy(api.app)
ma = Marshmallow(api.app)

class User(db.Model):
    user_id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(120), unique=True, nullable=False)
    username = db.Column(db.String(32), unique=True, nullable=False)
    password = db.Column(db.String(32))
    first_name = db.Column(db.String(32))
    last_name = db.Column(db.String(32))
    ...
...

class UserManager(Resource):
    @user.route('/get/<user_id>', methods = ['GET'])
    def get_user(user_id):
        ...

This of course results in errors due to circular imports. Question is, how do I separate the flask files with the routes from the api file when the blueprint has dependencies from the api (the db and the api objects)

I also somehow have to do something like api.add_resource(UserManager, '/api/users') but I'm not sure where that'd go given the circular import.

Tried reducing dependencies between two files, but couldn't achieve described goal without doing a 2 way import.

Either trying to get 2 way import to work or still have same structure of separate files with routes but using 1 way import.

CodePudding user response:

This is a well known problem in flask. The solution is to use application factories.

Cookiecutter Flask does this really well and offers a good template. It is well worth to check out their repo and try to understand what they are doing.

Assuming you have a folder app and this folder contains a file __init__.py and your other files user.py, etc.

  1. Create a file app/extensions.py with this content and any other extension you need to initialize.
...
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()
...
  1. Import the db object (which was created, but not initialized) in the files where you need it.
from app.extensions import db
  1. In your app/api.py file
from flask import Flask
from app.extensions import db
from app.user import user as user_bp

def create_app():
    app = Flask(__name__)
    register_extensions(app)
    register_blueprints(app)
    return app

def register_extensions(app):
    """Register Flask extensions."""
    db.init_app(app)
    return None

def register_blueprints(app):
    """Register Flask blueprints."""
    app.register_blueprint(user_bp)
    return None

if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)

Add stuff based on this approach as needed.

  • Related