I have a file app.py
like this:
import os
from dotenv import load_dotenv
from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, jwt_required, get_jwt_identity, create_access_token, create_refresh_token
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_cors import CORS
from datetime import timedelta
load_dotenv()
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('SQLALCHEMY_DATABASE_URI')
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY')
db = SQLAlchemy(app)
CORS(app)
jwt = JWTManager(app)
# ------------------------------ DB SCHEMA ------------------------------
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.String(50), nullable=False)
class Customer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), nullable=False)
phone = db.Column(db.String(120), nullable=False)
# --------------- LOGIN ENDPOINT --------------
@app.route('/login', methods=['POST'])
def login():
username = request.json.get('username', '')
password = request.json.get('password', '')
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
access_token = create_access_token(identity=username, fresh=True, expires_delta=timedelta(minutes=30))
refresh_token = create_refresh_token(identity=username)
return jsonify(access_token=access_token, refresh_token=refresh_token), 200
return jsonify({"message": "Invalid credentials"}), 401
if __name__ == '__main__':
app.run(debug=True)
I'm trying to separate the DB SCHEMA and the API into two separated file.
The problem is that if I create a file containing the DB schema and another one containing the app I have a circular importing error
I would recommend reading the Flask documentation on blueprints: https://flask.palletsprojects.com/en/3.0.x/blueprints/
Blueprints lets you separate an application's routes from the (possibly global) application object.
You should also separate the definition and initialization of the SQLAlchemy object, i.e.:
### file my_flask_app.py:
from my_db import db
from my_blueprint import my_blueprint
app = Flask(__name__)
db.init_app(app)
app.register_blueprint(my_blueprint)
app.run(debug=True)
### file my_db.py:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
...
class Customer(db.Model):
...
### file my_blueprint.py
from flask import Blueprint
from my_db import User
my_blueprint = Blueprint('my_blueprint', __name__)
@my_blueprint.route('/login', methods=['POST'])
def login():
username = request.json.get('username', '')
password = request.json.get('password', '')
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password):
access_token = create_access_token(identity=username, fresh=True, expires_delta=timedelta(minutes=30))
refresh_token = create_refresh_token(identity=username)
return jsonify(access_token=access_token, refresh_token=refresh_token), 200
return jsonify({"message": "Invalid credentials"}), 401