Opened 3 weeks ago

Closed 12 days ago

#36791 closed Bug (fixed)

Migration does not drop old M2M through-table when ManyToManyField target model changes

Reported by: Johanan Oppong Amoateng Owned by: Johanan Oppong Amoateng
Component: Migrations Version: 6.0
Severity: Normal Keywords:
Cc: Johanan Oppong Amoateng Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When changing the target model of a ManyToManyField, the migration autodetector generates only an AlterField operation. Django does not create a RemoveField + AddField sequence, and the old automatically generated through-table is left in place.

This results in the database schema no longer matching the model definitions. In my case, the stale through-table caused inconsistent M2M behaviour and errors when interacting with the relationship. No data records were lost, but the schema was incorrect until manually fixed.

This behaviour appears inconsistent with how Django handles other destructive schema changes.

Change History (15)

comment:1 by Jacob Walls, 3 weeks ago

Component: Database layer (models, ORM)Migrations
Triage Stage: UnreviewedAccepted
Type: UncategorizedBug

Thanks, replicated. Patch looks straightforward, would you be willing to submit a PR and extrapolate from similar existing test cases?

  • django/db/migrations/autodetector.py

    diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py
    index 7cc22c0637..fca73a675d 100644
    a b class MigrationAutodetector:  
    13391339            if old_field_dec != new_field_dec and old_field_name == field_name:
    13401340                both_m2m = old_field.many_to_many and new_field.many_to_many
    13411341                neither_m2m = not old_field.many_to_many and not new_field.many_to_many
    1342                 if both_m2m or neither_m2m:
     1342                target_changed = both_m2m and new_field_dec[2]["to"] != old_field_dec[2]["to"]
     1343                if (both_m2m or neither_m2m) and not target_changed:
    13431344                    # Either both fields are m2m or neither is
    13441345                    preserve_default = True
    13451346                    if (

comment:2 by Johanan Oppong Amoateng, 3 weeks ago

Yes please i will submit a patch for this

comment:3 by Johanan Oppong Amoateng, 3 weeks ago

Owner: set to Johanan Oppong Amoateng
Status: newassigned

comment:4 by Johanan Oppong Amoateng, 3 weeks ago

Has patch: set

comment:5 by Clifford Gama, 2 weeks ago

Patch needs improvement: set

comment:6 by Johanan Oppong Amoateng, 2 weeks ago

Patch needs improvement: unset

comment:7 by Clifford Gama, 2 weeks ago

Triage Stage: AcceptedReady for checkin

comment:8 by Clifford Gama, 2 weeks ago

Triage Stage: Ready for checkinAccepted

comment:9 by Jacob Walls, 2 weeks ago

Patch needs improvement: set

comment:10 by Johanan Oppong Amoateng, 2 weeks ago

Patch needs improvement: unset

comment:11 by Jacob Walls, 13 days ago

Patch needs improvement: set

comment:12 by Johanan Oppong Amoateng, 13 days ago

Has patch: unset

comment:13 by Johanan Oppong Amoateng, 13 days ago

Has patch: set
Patch needs improvement: unset

comment:14 by Clifford Gama, 13 days ago

Triage Stage: AcceptedReady for checkin

comment:15 by Jacob Walls <jacobtylerwalls@…>, 12 days ago

Resolution: fixed
Status: assignedclosed

In 33a0a6f0:

Fixed #36791 -- Made MigrationAutodetector recreate through table when m2m target model changes.

Co-Authored-By: Jacob Walls <38668450+jacobtylerwalls@…>
Co-Authored-By: Clifford Gama <cliffygamy@…>

Note: See TracTickets for help on using tickets.
Back to Top