#34881: Model-rename migration fails with IntegrityError if m2m relations to
self
exist
-------------------------------+--------------------------------------
Reporter: dennisvang | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: 4.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Description changed by dennisvang:
Old description:
> == Description
>
> Please consider the (contrived) minimal example below, part of an app
> called `myapp`:
>
> {{{
> class Person(models.Model):
> name = models.CharField(max_length=255)
> children = 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
>
> 1. start a new project, start a new app called `myapp`, with models as
> above.
> 2. run `makemigrations` and `migrate`
> 2. 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}}
> ]
> }}}
> 4. rename the `Person` model to e.g. `Foo` and update all references in
> code
> 5. run `makemigrations` and `migrate` again
>
> == 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.
New description:
== 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
1. start a new project, start a new app called `myapp`, with models as
above.
2. run `makemigrations` and `migrate`
2. 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}}
]
}}}
4. rename the `Person` model to e.g. `Foo` and update all references in
code
5. run `makemigrations` and `migrate` again
== 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.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/34881#comment:6>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018adc6aaedc-f28fcddd-05ab-4a83-92a6-4c1094841306-000000%40eu-central-1.amazonses.com.