#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.

Reply via email to