Skip to content

Make 0001_initial idempotent and swappable-user-model safe (0.5.0) - #1

Merged
mpasternak merged 1 commit into
mainfrom
idempotent-swappable-initial
May 31, 2026
Merged

mpasternak merged 1 commit into
mainfrom
idempotent-swappable-initial

Conversation

@mpasternak

Copy link
Copy Markdown
Member

Summary

Rework 0001_initial so it builds the dynamic_columns_* tables through the schema editor (create_model), guarded to run only when the tables are absent, instead of a plain CreateModel. The model side stays in state_operations, so Django's migration state is unchanged.

Two payoffs for downstream projects:

  1. Pre-existing schema no longer collides. Projects extracted from an older in-tree app (notably BPP, whose dynamic_columns app created these tables years ago) can apply 0001_initial onto a database that already carries the tables — it detects them and no-ops. Such projects no longer need a MIGRATION_MODULES override; they can consume this migration directly.
  2. Custom user models resolve correctly on a from-empty build. The user FK is materialised by the schema editor against settings.AUTH_USER_MODEL, so a fresh migrate / migrate --create-db on a project with a swapped user model points the FK at the right table instead of a hard-coded auth_user.

Why it's safe to change a released migration

  • The end state is identical (same CreateModel pair + constraints, now under SeparateDatabaseAndState), so databases that already recorded 0001_initial as applied are untouched and makemigrations --check reports no drift.
  • On a fresh install the guard's create_model produces exactly the same DDL as the old CreateModel.

Tests

  • New tests/test_migrations.py: re-applies the initial migration onto pre-existing tables and asserts no collision (the legacy-upgrade scenario). Fails against the old plain CreateModel, passes now.
  • Full suite green (55 passed) — every test relies on the fresh-build path for setup, so schema creation + constraints are exercised throughout.

Bumps version to 0.5.0 + CHANGELOG.

Downstream

BPP drops its bpp.migration_overrides.dynamic_admin_columns override and requires >=0.5.0 once this is released (iplweb/bpp PR forthcoming).


🤖 Generated with Claude Code

Build the dynamic_columns_* tables through the schema editor
(create_model), guarded to run only when the tables are absent, instead
of a plain CreateModel. This fixes two problems for downstream projects:

- Pre-existing schema no longer collides. Projects extracted from an
  older in-tree app (notably BPP) already carry these tables; applying
  0001_initial onto such a database now detects them and no-ops, so the
  MIGRATION_MODULES override they used to ship is no longer needed.

- Custom user models resolve correctly on a from-empty build. The user
  FK is materialised against settings.AUTH_USER_MODEL by the schema
  editor, so a fresh migrate on a project with a swapped user model
  (e.g. bpp.BppUser -> bpp_bppuser) no longer fails resolving a
  hard-coded auth_user table.

Migration state is unchanged (CreateModel pair + constraints under
SeparateDatabaseAndState); already-applied DBs are untouched and
makemigrations detects no drift. Adds a regression test that re-applies
the initial migration onto pre-existing tables. Bumps to 0.5.0.
@mpasternak
mpasternak merged commit 80d35f1 into main May 31, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant