#35434: prefetch_related_objects fails to cache UUID FKs when the string
representation of a UUID is used
-------------------------------------+-------------------------------------
Reporter: Selcuk Ayguney | 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 Ayguney:
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.
>
> Unit test to reproduce the issue:
> https://github.com/django/django/pull/18132
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 and the suggested fix:
https://github.com/django/django/pull/18132
--
--
Ticket URL: <https://code.djangoproject.com/ticket/35434#comment:2>
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/0107018f4892e9c1-9c883fdf-c0b3-421d-bf88-d7da3b2213e1-000000%40eu-central-1.amazonses.com.