#35434: prefetch_related_objects fails to cache UUID FKs when the string representation of a UUID is used -------------------------------------+------------------------------------- Reporter: selcuk | Owner: nobody Type: Bug | Status: new Component: Database layer | Version: dev (models, ORM) | 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 selcuk:
Old description: > Consider the following models: > > {{{ > class Pet(models.Model): > id = models.UUIDField(primary_key=True, default=uuid.uuid4, > editable=False) > name = models.CharField(max_length=20) > > class Toy(models.Model): > pet = models.ForeignKey(Pet, models.CASCADE, related_name="toys") > name = models.CharField(max_length=20) > }}} > The following works and caches the deferred {{{pet}}} instance as > expected: > {{{ > pet = Pet.objects.create(name="Fifi") > toy_bone = Toy(pet_id=str(pet.id), name="Bone") > print(toy_bone.pet) > }}} > It fails if {{{prefetch_related_objects}}} is used: > {{{ > pet = Pet.objects.create(name="Fifi") > toy_bone = Toy(pet_id=str(pet.id), name="Bone") > prefetch_related_objects([toy_bone], "pet") > print(toy_bone.pet) > }}} > {{{ > raise self.RelatedObjectDoesNotExist( > ^^^^^^^^^^^^^^^^^ > prefetch_related.models.Toy.pet.RelatedObjectDoesNotExist: Toy has no > pet. > }}} > The behaviour is inconsistent as str to UUID conversion is automatically > performed in the first example. > > One may argue that the use of {{{prefetch_related_objects}}} is redundant > in this case. However, it is useful in async code where deferred lookups > are not automatic. New description: Consider the following models: {{{ class Pet(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=20) class Toy(models.Model): pet = models.ForeignKey(Pet, models.CASCADE, related_name="toys") name = models.CharField(max_length=20) }}} The following works and caches the deferred {{{pet}}} instance as expected: {{{ pet = Pet.objects.create(name="Fifi") toy_bone = Toy(pet_id=str(pet.id), name="Bone") print(toy_bone.pet) }}} It fails if {{{prefetch_related_objects}}} is used: {{{ pet = Pet.objects.create(name="Fifi") toy_bone = Toy(pet_id=str(pet.id), name="Bone") prefetch_related_objects([toy_bone], "pet") print(toy_bone.pet) }}} {{{ raise self.RelatedObjectDoesNotExist( ^^^^^^^^^^^^^^^^^ prefetch_related.models.Toy.pet.RelatedObjectDoesNotExist: Toy has no pet. }}} The behaviour is inconsistent as str to UUID conversion is automatically performed in the first example. One may argue that the use of {{{prefetch_related_objects}}} is redundant in this case. However, it is useful in async code where deferred lookups are not automatic. Unit test to reproduce the issue: https://github.com/django/django/pull/18132 -- -- Ticket URL: <https://code.djangoproject.com/ticket/35434#comment:1> 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 django-updates+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/0107018f482a877f-361d5190-fa3d-493a-b85a-ffeda76a4fa2-000000%40eu-central-1.amazonses.com.