Changes between Initial Version and Version 3 of Ticket #37031


Ignore:
Timestamp:
Apr 14, 2026, 5:48:05 AM (4 weeks ago)
Author:
Clifford Gama
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #37031

    • Property Cc MANAS MADESHIYA Shai Berger Markus Holtermann added
    • Property Summary Improve "Writing migrations" how-to -- unique fields and ManyToManyField through modelsImprove writing migrations guide to adding unique fields on existing table
    • Property Type BugCleanup/optimization
    • Property Version 6.0dev
  • Ticket #37031 – Description

    initial v3  
    1 In the writing migrations docs there are two advanced migration scenarios that have inaccuracies and could be made clearer.
    2 
    3 **Migrations that add unique fields**
    4 
    511. The current approach splits the work across three files: one to add the field, one to populate values, and one to restore the constraint. All three operations can be placed in a single migration, which is simpler to follow and has the added benefit of being atomic — removing the race condition that is currently warned about in the docs.
    62
     
    84
    953. No mention of performant alternatives for large tables: The `RunPython` example iterates row by row with individual saves. For large tables this will be very slow. The docs should note that `QuerySet.bulk_update()` or RunSQL are worth considering in that case.
    10 
    11 **Changing a ManyToManyField to use a through model**
    12 
    13 1. Inaccurate description of how Django handles this change: The section states that "the default migration will delete the existing table and create a new one". This is not accurate. Django [https://github.com/django/django/blob/d61f33f03b3177afdf1d76153014bad4107b1224/django/db/backends/base/schema.py#L894 refuses to apply a migration] when `through=` is added/changed on an existing `ManyToManyField`.
    14 
    15 2. The through model example does not accurately reflect the database: The current example uses `on_delete=DO_NOTHING` and `models.UniqueConstraint`, whereas Django's auto-generated through tables use `CASCADE` and `unique_together`. Since the state and database are not in sync, I think this could cause issues in later migrations.
    16 
    17 3. The example can be simplified by setting `Meta.db_table` on the new through model to match the existing table name, eliminating the need for a `RunSQL` rename operation.
    18 
    19 The section also suggests using `sqlmigrate` or `dbshell` to find the existing table name, which is indirect. The simplest approach is to inspect `field.through._meta.db_table` before modifying the field.
Back to Top