Fixed #28375 -- Fixed KeyError crash on reverse prefetch of a model with OneToOneField primary key to a non-pk field.
This commit is contained in:
parent
b5ad5c628a
commit
fea9cb46aa
|
@ -63,8 +63,6 @@ and two directions (forward and reverse) for a total of six combinations.
|
|||
``ReverseManyToManyDescriptor``, use ``ManyToManyDescriptor`` instead.
|
||||
"""
|
||||
|
||||
from operator import attrgetter
|
||||
|
||||
from django.db import connections, router, transaction
|
||||
from django.db.models import Q, signals
|
||||
from django.db.models.query import QuerySet
|
||||
|
@ -334,11 +332,8 @@ class ReverseOneToOneDescriptor:
|
|||
queryset = self.get_queryset()
|
||||
queryset._add_hints(instance=instances[0])
|
||||
|
||||
rel_obj_attr = attrgetter(self.related.field.attname)
|
||||
|
||||
def instance_attr(obj):
|
||||
return obj.pk
|
||||
|
||||
rel_obj_attr = self.related.field.get_local_related_value
|
||||
instance_attr = self.related.field.get_foreign_related_value
|
||||
instances_dict = {instance_attr(inst): inst for inst in instances}
|
||||
query = {'%s__in' % self.related.field.name: instances}
|
||||
queryset = queryset.filter(**query)
|
||||
|
|
|
@ -65,7 +65,12 @@ class BookWithYear(Book):
|
|||
|
||||
|
||||
class Bio(models.Model):
|
||||
author = models.OneToOneField(Author, models.CASCADE)
|
||||
author = models.OneToOneField(
|
||||
Author,
|
||||
models.CASCADE,
|
||||
primary_key=True,
|
||||
to_field='name',
|
||||
)
|
||||
books = models.ManyToManyField(Book, blank=True)
|
||||
|
||||
|
||||
|
|
|
@ -81,6 +81,23 @@ class PrefetchRelatedTests(TestCase):
|
|||
with self.assertRaises(BookWithYear.DoesNotExist):
|
||||
book.bookwithyear
|
||||
|
||||
def test_onetoone_reverse_with_to_field_pk(self):
|
||||
"""
|
||||
A model (Bio) with a OneToOneField primary key (author) that references
|
||||
a non-pk field (name) on the related model (Author) is prefetchable.
|
||||
"""
|
||||
Bio.objects.bulk_create([
|
||||
Bio(author=self.author1),
|
||||
Bio(author=self.author2),
|
||||
Bio(author=self.author3),
|
||||
])
|
||||
authors = Author.objects.filter(
|
||||
name__in=[self.author1, self.author2, self.author3],
|
||||
).prefetch_related('bio')
|
||||
with self.assertNumQueries(2):
|
||||
for author in authors:
|
||||
self.assertEqual(author.name, author.bio.author.name)
|
||||
|
||||
def test_survives_clone(self):
|
||||
with self.assertNumQueries(2):
|
||||
[list(b.first_time_authors.all())
|
||||
|
|
Loading…
Reference in New Issue