I've been struggling with this issue on and off for quite some time, and strangely could not find a straightforward question/answer combo on this on SO. Related questions here and here. I finally found a solution so I will ask and answer my own question.
In Flask SQLAlchemy (and regular SQLAlchemy), you can have a column like this:
class Character(db.model):
background_id = db.Column(db.Integer, db.ForeignKey('backgrounds.id'))
When you run flask db migrate
, or alembic revision --autogenerate
, this will result in an operation that looks like this:
def upgrade():
op.create_foreign_key(None, 'characters', 'backgrounds', ['background_id'], ['id'])
def downgrade():
op.drop_constraint(None, 'characters', type_='foreignkey')
The None
here is bad. In fact, if you try to downgrade later, this will always fail, because drop_constraint
needs the name of the constraint.
You can change this every time you generate a migration, like this:
def upgrade():
op.create_foreign_key('fk_characters_backgrounds', 'characters', 'backgrounds', ['background_id'], ['id'])
def downgrade():
op.drop_constraint('fk_characters_backgrounds', 'characters', type_='foreignkey')
Which works!
But if you're like me, you don't want to have to remember to do this every time you autogenerate a revision with a foreign key.
So the question is, how can we make this automatic?