This version is in beta. Some features may change before release.

Renaming models

How autodetection handles a renamed model, and how to resolve an ambiguous rename-vs-drop safely.

Renaming models

When you rename a model, makemigrations has to decide whether you renamed an existing table (keep its rows) or dropped one and created another (start empty). It uses two signals.

Struct-name match — resolved automatically

If the Rust struct keeps its name but its table changes (e.g. you set a new #[umbral(table = "...")]), that's an unambiguous rename. Autodetection emits a RenameTable and moves the rows. Nothing to do.

Column-shape match — you decide

If both the struct name and the table change, autodetection can only compare column shapes. A dropped model and a new model with a bit-identical shape is genuinely ambiguous:

  • it could be a rename (move the old rows to the new name), or
  • two unrelated models that happen to share a shape (drop the old, create the new empty).

Guessing either way is a silent data bug — auto-renaming hands one model's rows to another and skips the intended drop; auto-dropping deletes rows you meant to keep. So makemigrations fails closed and asks you to choose:

Code
txt
umbral makemigrations: ambiguous rename — the dropped model `foo` and the new
model `bar` have identical column shapes ... Resolve it: set
UMBRAL_MIGRATIONS_ASSUME_RENAMES=assume ... or =independent ...

Resolve it with one environment variable:

Warning
The setting applies to the whole `makemigrations` run. If one change is a rename and another is a coincidental shot in a single run, split them into two runs so you can set the right intent for each — or hand-write the `RenameTable` op into the migration file.

Renaming a model with an M2M field

A model's many-to-many junction table is named <parent_table>_<field> (e.g. an Article with a tags: M2M<Tag> field owns article_tags). When you rename the parent — articlepost — the autodetector renames the junction too (article_tagspost_tags) instead of dropping and recreating it, so every relationship row is preserved. No extra step is required; makemigrations emits the RenameTable for the junction automatically alongside the parent's rename.

This works because the junction's columns are generic (parent_id / child_id, not article_id) and its foreign key to the parent is updated by the parent's own rename, so a table rename is all that's needed.

See also

  • Managed migrations — the declare → migrate loop.
  • Design rationale: planning/audit_2/AUDIT_REPORT.md (finding H23) and arch.md (autodetection).
migrationsrenameautodetectiondata-safety