Opened 10 years ago
Last modified 5 months ago
#23034 new New feature
Add migrations support for adding ManyToMany "through" model
Reported by: | 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 , 10 years ago
Summary: | Migrations fail with modified ManyToMany "through" model → Add migrations support for adding ManyToMany "through" model |
---|---|
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → New feature |
comment:2 by , 10 years ago
Triage Stage: | Accepted → Someday/Maybe |
---|
Triaging this to "someday/maybe". It would be nice, but it's a complex thing to add.
comment:3 by , 10 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Triage Stage: | Someday/Maybe → Accepted |
Version: | 1.7-rc-1 → master |
comment:5 by , 10 years ago
Patch needs improvement: | set |
---|
comment:6 by , 10 years ago
Patch needs improvement: | unset |
---|
comment:8 by , 9 years ago
Cc: | added |
---|
comment:9 by , 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 , 6 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:11 by , 6 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
comment:12 by , 6 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
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 , 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.
follow-up: 15 comment:14 by , 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()
.
comment:15 by , 5 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?
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.