#36839: Renaming of content types on RenameModel operations silently passes when
duplicates are found
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner: Moksha
| Choksi
Type: Bug | Status: closed
Component: | Version: 6.0
contrib.contenttypes |
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Jacob Walls):
Sure thing. With a fresh app:
1. add models:
{{{#!py
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class Song(models.Model):
melodious = models.BooleanField(default=True)
class Melody(models.Model):
melodious = models.BooleanField(default=True)
class TaggedSong(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType,
on_delete=models.CASCADE)
object_id = models.PositiveBigIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
}}}
2. `makemigrations` && `migrate`
3. In a shell:
{{{#!py
>>> song = Song.objects.create()
>>> tagged = TaggedSong(tag="hit", content_object=song)
>>> tagged.save()
}}}
4. Delete the melody class, makemigrations, migrate. You now have a stale
content type for the model "melody". Before, there used to be a
`post_migrate` handler alerting you to the situation.
5. Rename `Song` to `Melody`, makemigrations, migrate, answer "Renamed?"
with Y.
6. If you instrumented the `except IntegrityError` mentioned in the ticket
body, you hit that silent pass.
7. You can't look up your tagged items by their new model name, because
they were silently ignored:
{{{#!py
>>> TaggedSong.objects.filter(content_type__model="melody")
<QuerySet []>
>>> TaggedSong.objects.filter(content_type__model="song")
<QuerySet [<TaggedSong: TaggedSong object (1)>]>
}}}
If I were a little more fluent with content types and generic foreign keys
I could probably construct a scenario that would show lookups resulting in
`ObjectDoesNotExist`, the point is that the data didn't migrate. The
content type is now fresh:
{{{#!py
>>> ContentType.objects.get_for_model(Melody)
<ContentType: Myapp | melody>
}}}
... but all your data is on the old one (see step 7.)
--
Ticket URL: <
https://code.djangoproject.com/ticket/36839#comment:6>