Opened 7 years ago
Closed 2 years ago
#28987 closed Bug (fixed)
Migration changing ManyToManyField target to 'self' doesn't work correctly
Reported by: | MSleepyPanda | Owned by: | Bhuvnesh |
---|---|---|---|
Component: | Migrations | Version: | 2.0 |
Severity: | Normal | Keywords: | ManyToManyField |
Cc: | 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
Steps to reproduce:
Create Models:
class Bar(models.Model): pass class Foo(models.Model): bar = models.ManyToManyField('Bar', blank=True)
Migrate:
./manage.py makemigrations app ./manage.py migrate
Change type of the ManyToManyField to Foo:
class Bar(models.Model): pass class Foo(models.Model): bar = models.ManyToManyField('Foo', blank=True)
Migrate (see above)
In the admin page, navigate to "add Foo", click save
You should see an OperationalError, "no such column: app_foo_bar.from_foo_id"
Change History (16)
comment:1 by , 7 years ago
Summary: | makemigrations doesn't catch ManyToManyField type change, leaves DB in inconsistent state → Migration changing ManyToManyField target to 'self' doesn't work correctly |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 7 years ago
Needs tests: | set |
---|---|
Owner: | changed from | to
Status: | new → assigned |
follow-up: 4 comment:3 by , 7 years ago
Can I check out what you want? You can use 'self' instead of 'Foo' like this :
class Foo(models.Model): bar = models.ManyToManyField('self', blank=True)
You meant that we should use 'Foo' rather than 'self', right?
comment:4 by , 7 years ago
Replying to SShayashi:
Can I check out what you want? You can use 'self' instead of 'Foo' like this :
class Foo(models.Model): bar = models.ManyToManyField('self', blank=True)You meant that we should use 'Foo' rather than 'self', right?
Exactly, though i wasn't aware that self
would work in that context. I think i like naming the type directly more, since self
could be easily confused with the self
argument of class methods.
comment:5 by , 4 years ago
Needs tests: | unset |
---|
comment:6 by , 4 years ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:7 by , 2 years ago
Owner: | set to |
---|---|
Status: | new → assigned |
comment:8 by , 2 years ago
While altering a many to many field , a new table is created (which is later renamed) and data is copied from old table to new table and then old table is deleted. This issue caused while making this new table here, we are only altering the m2m_reverse_fields
ignoring the m2m_fields
that points to our model. But both m2m_reverse_fields
and m2m_fields
needs to be changed.
Hope i'm proceeding into the right direction.
comment:9 by , 2 years ago
It is also failing for the case if process is reversed, like when we migrate passing self/Foo to the m2m field and then change it to Bar.(due to the same reason that we are not altering m2m_fields
)
comment:10 by , 2 years ago
Hi Bhuvnesh
I tried to alter self pointing field and with the changes below its working as expected for the above issue and passing all the tests as well.
If the tests are all passing it's worth opening a PR to make review easier. (Make sure to add a new test for the issue here too.)
Thanks.
comment:12 by , 2 years ago
Has patch: | set |
---|
comment:13 by , 2 years ago
Patch needs improvement: | set |
---|
comment:14 by , 2 years ago
Patch needs improvement: | unset |
---|
comment:15 by , 2 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
I believe it works correctly as long as the new target model isn't 'self'.