Recreating Foreign Keys with Alembic
Alembic is a great tool for keeping track of schema changes in python applications. I am using it to manage DB migrations for braindump along with Flask SQL Alchemy as my ORM. One challenge is managing proper foreign key constraints. By default if you define a foreign key relationship in your schema definition it will not generate the proper migration code. For example, in braindump we have a one to many relationship between users and notes.
class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(254), unique=True, index=True) password_hash = db.Column(db.String(256)) confirmed = db.Column(db.Boolean, default=False) avatar_hash = db.Column(db.String(32)) created_date = db.Column(db.DateTime(), default=datetime.utcnow) updated_date = db.Column(db.DateTime(), default=datetime.utcnow)<span class="nx">notes</span> <span class="o">=</span> <span class="nx">db</span><span class="p">.</span><span class="nx">relationship</span><span class="p">(</span> <span class="s1">'Note'</span><span class="p">,</span> <span class="nx">backref</span><span class="o">=</span><span class="s1">'author'</span><span class="p">,</span> <span class="nx">lazy</span><span class="o">=</span><span class="s1">'dynamic'</span><span class="p">,</span> <span class="nx">cascade</span><span class="o">=</span><span class="s2">"all, delete-orphan"</span><span class="p">)</span>
sa.ForeignKeyConstraint(['author_id'], ['users.id'], ),
ondelete action. What we actually want is something like this:sa.ForeignKeyConstraint(['author_id'], ['users.id'], ondelete='CASCADE')
ondelete='CASCADE' will create the proper relationship. If you are like me, and do not catch this, then you will need to run a second migration to remove and recreate these keys. The migration code to do this is shown below:from alembic import op import sqlalchemy as sadef upgrade(): with op.batch_alter_table(“notes”) as batch_op: batch_op.drop_constraint( “notes_author_id_fkey”, type_=“foreignkey”) op.create_foreign_key( “notes_author_id_fkey”, “notes”, “users”, [“author_id”], [“id”], ondelete=“CASCADE”)
Thank you for reading! Share your thoughts with me on bluesky, mastodon, or via email.
Check out some more stuff to read down below.
Most popular posts this month
- SQLite DB Migrations with PRAGMA user_version
- Using cgit
- My Custom Miniflux CSS Theme
- Setting up ANTLR4 on Windows
- Making cgit Pretty
Recent Favorite Blog Posts
This is a collection of the last 8 posts that I bookmarked.
- Pluralistic: Enshittification and Reverse Centaurs go global (29 Jul 2026) from Pluralistic: Daily links from Cory Doctorow
- AI Mania Is Eviscerating Global Decision-Making from Ludicity
- No-One Escapes the Permanent Underclass from Fernando Borretti
- Is it ethical to use AI? from charity.wtf
- The logical destination of LLMs from Andy Bell
- Revised rules of engineering leadership. from Irrational Exuberance
- The circus freaks of open source from Drew DeVault's blog
- Clanker: A Word For The Machine from Armin Ronacher's Thoughts and Writings
Articles from blogs I follow around the net
Hacking Workshop for September 2026
I'm pleased to announce that David Rowley will be joining us in September to discuss his talk Optimizing code in the hot path; with examples from tuple deformation. If you're interesting in joining us, please sign up using this form and I will send you an...
via Robert Haas July 31, 2026One and one thing only
I wanted to show you a year’s worth of messages from my barber’s software, because this is what software should be. No spam, no upsells, no growth hacks, no unwelcome cuteness or puzzling verbosity. It’s so curt and straight to the point it should be set i...
via Unsung July 31, 2026Pluralistic: Better to beg forgiveness (31 Jul 2026)
Today's links Better to beg forgiveness: Don't ring the doorbell at the house of no unless you absolutely must. Hey look at this: Delights to delectate. Object permanence: RIP Poul Anderson; P2P at PC Forum; Waitress handed her own stolen ID by carded dine...
via Pluralistic: Daily links from Cory Doctorow July 31, 2026Generated by openring