Opened 5 years ago

Last modified 4 months ago

#23034 new New feature

Add migrations support for adding ManyToMany "through" model

Reported by: lorinkoz@… Owned by:
Component: Migrations Version: master
Severity: Normal Keywords:
Cc: carsten.fuchs@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Adding a "through" model on a ManyToMany field make "makemigrations" fail with an explicit error stating that it is not possible. I have worked it around by renaming the field, creating the migration (so as to make Django believe it's a new field) and then renaming the field back to the original name and creating another migration (which is correctly acknowledged by Django as a simple "renaming"). I understand the implications of adding a through model from the migrations perspective, but maybe a more friendly output could be achieved. Is it even possible to create some sort of interaction, like when you create a field with not null and no default value, so as to ask the user if they want to destroy/create a new field??

Change History (12)

comment:1 Changed 5 years ago by Tim Graham

Summary: Migrations fail with modified ManyToMany "through" modelAdd migrations support for adding ManyToMany "through" model
Triage Stage: UnreviewedAccepted
Type: UncategorizedNew feature

As Andrew noted in #22476, "as the error message says, you cannot alter an M2M without a through model into one with a through model, at least not in the current system." I'm not sure how feasible it will be to add support for thits, but tentatively accepting.

comment:2 Changed 5 years ago by Andrew Godwin

Triage Stage: AcceptedSomeday/Maybe

Triaging this to "someday/maybe". It would be nice, but it's a complex thing to add.

comment:3 Changed 4 years ago by Marten Kenbeek

Owner: changed from nobody to Marten Kenbeek
Status: newassigned
Triage Stage: Someday/MaybeAccepted
Version: 1.7-rc-1master

comment:4 Changed 4 years ago by Marten Kenbeek

Has patch: set

comment:5 Changed 4 years ago by Marten Kenbeek

Patch needs improvement: set

comment:6 Changed 4 years ago by Marten Kenbeek

Patch needs improvement: unset

comment:7 Changed 4 years ago by Tim Graham

Patch needs improvement: set

Markus reviewed the PR.

comment:8 Changed 4 years ago by Carsten Fuchs

Cc: carsten.fuchs@… added

comment:9 Changed 8 months ago by Simon Charette

FWIW a workaround for the current state of things, as long as through._meta.db_table points to the previously automatically generated db_table, is to wrap the generated operations in a SeparateDatabaseAndState.

comment:10 Changed 8 months ago by Marten Kenbeek

Owner: Marten Kenbeek deleted
Status: assignednew

comment:11 Changed 8 months ago by Simon Charette

Owner: set to Simon Charette
Status: newassigned

comment:12 Changed 4 months ago by Simon Charette

Owner: Simon Charette deleted
Status: assignednew

I'm not actively working on this ticket so I'll deassign myself but I made some progress by using a different approach.

My idea was to teach the auto-detector to detect ManyToMany(through) addition where through is a model compatible with the previously auto-created model. When it detected this case it would use the questioner to ask the user whether or not the previous table should be reused. On a "yes" a AddManyToManyThrough operation that has a noop database_forwards but an appropriate state_forwards to deal with the ModelState insertion would be added to the operations. If the new db_table wasn't matching or fields were added then the appropriate AlterModelTable and AddField operations would be added after the AddManyToManyThrough as well.

[CreateModel('Foo'), AddManyToManyThrough('Foo', 'bars', ManyToMany('Bar', through='FooBar')] could be optimized into
[CreateModel('Foo'), CreateModel('FooBar', fks), AddField('Foo', 'bars', ManyToMany('Bar', through='FooBar')] and the normal chain of optimizations could then take place.

The work so far is available on this branch

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