flask-restplus and sqlalchemy to design my backend. I am using flask-migrate library so that I can adjust my database tables when there is any such requirements.
Here is my directory structure
-mainfolder/
-app/
-v1/
-app.py
-apis/
-__init__.py
-some folders.
.
.
.
-database/
-__init__.py
-models.py
-config/
-__init__.py
-detect_config_file.py
-
-wsgi.py
The code in my app.py is
import logging.config
import json
import os
import sys
from flask import Flask, Blueprint
from flask_restplus import Api
from flask_jwt_extended import JWTManager
from flask_cors import CORS
from database import *
from config.detect_config_file import config
app = Flask(__name__)
cors = CORS(app)
api = Api(version='1.0', title='Plug-n-Play APIs',
description='Demostration of APIs behind plug-n-play dashboard')
logging_conf_path =
os.path.normpath(os.path.join(os.path.dirname(__file__), '../../logging.conf'))
logging.config.fileConfig(logging_conf_path)
log = logging.getLogger(__name__)
def configure_app(flask_app):
flask_app.config['JWT_SECRET_KEY'] = config['JWT_SECRET_KEY']
flask_app.config['JWT_BLACKLIST_ENABLED'] = config['JWT_BLACKLIST_ENABLED']
flask_app.config['JWT_BLACKLIST_TOKEN_CHECKS'] = config['JWT_BLACKLIST_TOKEN_CHECKS']
flask_app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://'+ config['DB_USERNAME'] + ':' + config['DB_PASSWORD']+'@'+ config['DB_HOST'] + '/' + config['DB_NAME']
flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = config['DB_TRACK_MODIFICATIONS']
def initialize_app(flask_app):
configure_app(flask_app)
blueprint = Blueprint('api', __name__, url_prefix='/api/v1')
api.init_app(blueprint)
flask_app.register_blueprint(blueprint)
db.init_app(flask_app)
with flask_app.app_context():
initDB()
jwt = JWTManager(flask_app)
def main():
initialize_app(app)
log.info('>>>>> Starting development server <<<<<')
app.run(debug=config['APP_DEBUG'], host="0.0.0.0")
if __name__ == "__main__":
main()
models.py file in database folder is
from database import db
#importing from __init__.py of database folder
from sqlalchemy.types import JSON
from sqlalchemy_utils.types.choice import ChoiceType
from config.detect_config_file import config
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app
#importing the flask app from app.py
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
class UserModel(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(120), unique = True, nullable = False)
if __name__ == '__main__':
manager.run()
the __init__.py file in the database folder is
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def initDB():
from database.models import *
db.create_all()
My thought process here is that when i run app.py then it will create the tables in my database(i have already created the database in mysql) the segment of code in app.py
with flask_app.app_context():
initDB()
when the schema changes then in that case my I will run these commands to update my databases without having to drop my database and create again.
$python models.py db init
$python models.py db migrate
$python models.py db upgrade
But this is not working. I am getting a circular dependency error when i try to import app from app in the models.py
Please have a look into my code and tell me if my approach is correct or there is a better way to do this. My main aim is to achieve the database migrations just like we have in django so that I can change my database schema easily.
models.pyand another in the__init__.pyof your database package. You should use a single database instance. The problem with the circular imports is the standard problem that occurs with Flask, you can address it by moving the database imports below the point whereappis created.