Hey folks!
I'd like to open a can of worms: SQLAlchemy integration in Flask. It's a long read but I hope you'll like it. I try not to be on the ranty side.
First, some context: we have been plagued by tech debt for a very long time, maybe more than other development projects because web tech has evolved very quickly in the past 15 years (after the big flatline of "I need to be IE6-compatible", but I digress), and also because we're a small team maintaining a ton of apps.
In the past, we've had to switch web frameworks a couple of times. Turbogears 1, then Turbogears 2, then Flask, but we also have apps in CherryPy (to this day!) and Pyramid (and somewhat Django although we're not maintaining them). As a result we've grown very suspicious of framework integration because that means more work when we (inevitably) have to migrate to a different framework. I think it's partly why we chose Flask at the time: it's a minimalist framework, therefore there will be less integration bits to migrate away from. I don't agree entirely with this point of view but I think the standardization has done us a lot of good.
We've also standardized on SQLAlchemy for our DB, which is great. But we haven't standardized on how to integrate the two. There's an integration library called Flask-SQLAlchemy, but our apps don't use it (to my knowledge). I think that the reason is that Flask-SQLAlchmemy makes your models unusable without Flask, and that triggers our "what if the framework goes away" PTSD. Here's an example of what models look like with Flask-SQLAlchemy:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False
As you can see, the User class inherits from db.Model, something that the Flask-SQLAlchemy extension provides. Same for the Column and the DB types. I do understand why it would make us flinch to "tie" our models to the web framework, even indirectly. (that said, if we want to migrate those models from Flask-SQLAlchemy to native SQLAlchemy, it would be so trivial that plain sed can handle it)
So we've tried to do the SQLAlchemy integration in Flask ourselves. This has two downsides:
- it's not as easy as it looks, especially when migrations and Alembic come into play
- we end up with many slightly different integrations, written by different people or even the same person at different points in time.
Ironically, our attempt at avoiding tech debt has caused us more tech debt.