Opened 10 years ago

Last modified 6 months ago

#23034 new New feature

Add migrations support for adding ManyToMany "through" model

Reported by: lorinkoz@… Owned by:
Component: Migrations Version: dev
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 (15)

comment:1 by Tim Graham, 10 years ago

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 by Andrew Godwin, 10 years ago

Triage Stage: AcceptedSomeday/Maybe

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

comment:3 by Marten Kenbeek, 10 years ago

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

comment:5 by Marten Kenbeek, 10 years ago

Patch needs improvement: set

comment:6 by Marten Kenbeek, 10 years ago

Patch needs improvement: unset

comment:7 by Tim Graham, 10 years ago

Patch needs improvement: set

Markus reviewed the PR.

comment:8 by Carsten Fuchs, 9 years ago

Cc: carsten.fuchs@… added

comment:9 by Simon Charette, 6 years ago

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 by Marten Kenbeek, 6 years ago

Owner: Marten Kenbeek removed
Status: assignednew

comment:11 by Simon Charette, 6 years ago

Owner: set to Simon Charette
Status: newassigned

comment:12 by Simon Charette, 6 years ago

Owner: Simon Charette removed
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

comment:13 by Carsten Agger, 5 years ago

As a developer bitten by this I'd like to second this motion: A customer changed their data model mid-project, and now we need to add fields to a many-to-many relationship & I'm looking at a) deleting all migrations and reinitializing the DB or b) make one of the workarounds here play without being too much of a hack.

I'd be grateful to be able to do this automatically one day, I think the use case is common enough.

comment:14 by Mariusz Felisiak, 2 years ago

As far as I'm aware, this transformation is too fragile to be automated (see https://youtu.be/4QF9UHEFPCY). It's also documented how to do this with SeparateDatabaseAndState().

in reply to:  14 comment:15 by Shai Berger, 6 months ago

Replying to Mariusz Felisiak:

As far as I'm aware, this transformation is too fragile to be automated (see https://youtu.be/4QF9UHEFPCY). It's also documented how to do this with SeparateDatabaseAndState().

Nobody had anything to say about this for three years before that comment, and 18 months after... maybe it's time to wontfix this ticket?

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