Opened 2 years ago
Last modified 17 months ago
#34881 closed Bug
Model-rename migration fails with IntegrityError if m2m relations to self exist — at Version 6
| Reported by: | dennisvang | Owned by: | nobody |
|---|---|---|---|
| Component: | Migrations | Version: | dev |
| Severity: | Normal | Keywords: | sqlite |
| Cc: | Simon Charette, Mariusz Felisiak, David Wobrock, Jase Hackman | 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 (last modified by )
Description
Please consider the (contrived) minimal example below, part of an app called myapp:
class Person(models.Model):
name = models.CharField(max_length=255)
relatives = models.ManyToManyField(
to='self', through='myapp.Relation', blank=True
)
class Relation(models.Model):
parent = models.ForeignKey(
to='myapp.Person',
related_name='relations_as_parent',
on_delete=models.CASCADE,
)
child = models.ForeignKey(
to='myapp.Person',
related_name='relations_as_child',
on_delete=models.CASCADE,
)
Now suppose I rename the Person model to Foo and update corresponding references.
Then I run manage.py makemigrations, which correctly recognizes that the model has been renamed.
Now, applying this migration to an empty database works, without issue, but applying the migration to a database with existing data fails with an IntegrityError.
Steps to reproduce
- start a new project, start a new app called
myapp, with models as above. - run
makemigrationsandmigrate - Load (valid) data from the following fixture:
[ {"model": "myapp.person", "pk": 1, "fields": {"name": "Jenny"}}, {"model": "myapp.person", "pk": 2, "fields": {"name": "Johnny"}}, {"model": "myapp.person", "pk": 3, "fields": {"name": "Mom"}}, {"model": "myapp.person", "pk": 4, "fields": {"name": "Dad"}}, {"model": "myapp.relation", "pk": 1, "fields": {"parent": 3, "child": 1}}, {"model": "myapp.relation", "pk": 2, "fields": {"parent": 3, "child": 2}}, {"model": "myapp.relation", "pk": 3, "fields": {"parent": 4, "child": 1}}, {"model": "myapp.relation", "pk": 4, "fields": {"parent": 4, "child": 2}} ] - rename the
Personmodel to e.g.Fooand update all references in code - run
makemigrationsandmigrateagain
What happens
The migrate command fails with
django.db.utils.IntegrityError: The row in table 'myapp_relation' with primary key '1' has an invalid foreign key: myapp_relation.child_id contains a value '1' that does not have a corresponding value in myapp_person.id.
But a Person with id=1 does exist in the database.
What I would expect to happen
I would expect this to work without any problems.
Notes
I also tried the same steps with an implicit through model , i.e. children = models.ManyToManyField(to='self', blank=True).
This works without issue.
Change History (6)
comment:1 by , 2 years ago
| Summary: | Migration fails with IntegrityError after renaming model with existing m2m relations to self → Migration fails with IntegrityError after renaming model if m2m relations to self exist |
|---|
comment:2 by , 2 years ago
| Summary: | Migration fails with IntegrityError after renaming model if m2m relations to self exist → Model rename fails during migration if m2m relations to self exist |
|---|
comment:3 by , 2 years ago
| Summary: | Model rename fails during migration if m2m relations to self exist → Model-rename migration fails with IntegrityError if m2m relations to self exist |
|---|
comment:4 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:5 by , 2 years ago
| Description: | modified (diff) |
|---|
comment:6 by , 2 years ago
| Description: | modified (diff) |
|---|