I'm getting into Flask and building out an app that uses Flask SQLAlchemy. I've created a basic API that works when all the code is in a single file, but would like to better organize it, like so:
app/models/user.py
from datetime import datetime
from app.app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
public_id = db.Column(db.String, unique=True)
admin = db.Column(db.Boolean)
username = db.Column(db.String(50), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(100))
subscription_plan = db.Column(db.Integer)
created_at = db.Column(db.DateTime, index=True,
default=datetime.utcnow())
updated_at = db.Column(db.DateTime, index=True, default=datetime.utcnow())
app/app.py
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash
import uuid
from app.models.user import User
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = #SQLALCHEMY_DATABASE_URI
db = SQLAlchemy(app)
# ... CRUD routes that will use User
@app.route('/user', methods=['POST'])
def create_user():
data = request.get_json()
hashed_password = generate_password_hash(data['password'])
new_user = User(
public_id=str(uuid.uuid4()),
username=data['username'],
password=hashed_password,
email=data['email'],
admin=data['admin'],
subscription_plan=data['subscription_plan']
)
db.session.add(new_user)
db.session.commit()
return jsonify({'message': 'User successfully created.'})
if __name__ == '__main__':
app.run(port=5000, debug=True)
I would like to import db
from app/app.py into my app/models/user.py file, but when I then try to import the User
model into app/app.py, it gives me an error because of the circular import. I have no idea how to get around this because it seems like User
needs db
after it gets passed an instance of app
from app/app.py.
I'd also like to move my routes out of here and into separate files for better organization, so trying to understand the best way to avoid circular imports all around. Any and all help is greatly appreciated!
Instead of having User import app and app import user, bring them together in init.
app/app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
app/models/user.py
from app.app import db
class User:
pass #access db the way you want
app/views.py
from app.app import app,db
@app.route("/")
def home():
return "Hello World" # use db as you want
app/__init__.py
from app import app
from app.models.user import User
from app import views
This is the leanest fix to the problem. However, I would recommend using Application Factories