简体   繁体   中英

Flask_SQLAlchemy modularization issues due ORM

I am trying to build an API using Flask. For database actions I use flask_sqlalchemy.

In my main file, the flask app is initalized. I pass the resulting instance to another file where the configuration is set and to my database module that handles database operations.

main.py:

app = flask.Flask(__name__)  # initialize flask app

#initialize modules with app
config.init(app)
database.init(app)

The problem is, the relations I use in the database are in a seperate file and it needs the db object to declare the classes for ORM.

My idea was to declare db and initialize it later in an init function, but that doesn't work in this case, because the db object is undefined when the pythonfile is loaded by an import.

relations.py

db: SQLAlchemy


def init(db):
    Relations.db = db


class Series(db.Model):
    """Representation of a series
    """
    id = db.Column(db.String(255), primary_key=True)
    title = db.Column(db.String(255))


class User(db.Model):
    """Representation of a user
    """
    id = db.Column(db.INT, primary_key=True)
    name = db.Column(db.String(255))


class Subscription(db.Model):
    """Representation of a subscription
    """

    series_id = db.Column(db.INT, primary_key=True)
    user_id = db.Column(db.String(255), primary_key=True)

My database module uses the way and it works fine( init .py file):

db: SQLAlchemy


def init(app):
    database.db = SQLAlchemy(app)

# handle database operations...

One approach to solve the issue is just using another instance in the relations.py like that:

app = flask.Flask(__name__)
db = SQLAlchemy(app)

# declare classes...

I tried it out and it workes, but that is not a nice way to solve this and leads to other problems. Importing it from main does also not work because of circular import.

I have no idea how to smoothly solve this without removing modularization. I would be thankful for any inputs. If I should add any further information, just let me know.

I would create the app variable in your main.py file but leave out the initializing part. From there you call a function from init.py to basically set up the database. That is what I did for my last flask project.

Main.py:

from init import create_app

app = create_app()

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

Init.py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
    
db = SQLAlchemy()
DB_NAME = "database.db"
    
    
def create_app():
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
    db.init_app(app)
    
    create_database(app)
    
    #Other operations ... 
    
    return app

Relations.py

from init import db 

#all your classes ...

db.create_all()

So now you can import the db object to your relations.py file from the init.py.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM