diff options
| author | can <cansarigol@derinbilgi.com.tr> | 2019-05-29 20:24:37 +0300 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2019-05-31 18:11:55 +0200 |
| commit | dffa3e1992562ba60512d96d1eb5859ffff2ceb5 (patch) | |
| tree | ce66a812bfa12e19e738bf105b62dbfdef7a2335 /django | |
| parent | f66021f3f773023d0c61d2537d5dd1e5e1740537 (diff) | |
Fixed #30493 -- Fixed prefetch_related() for GenericRelation with different content types.
Co-Authored-By: Mariusz Felisiak <felisiak.mariusz@gmail.com>
Thanks Simon Charette for the review.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/contenttypes/fields.py | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py index 62284e980e..4015f16c6b 100644 --- a/django/contrib/contenttypes/fields.py +++ b/django/contrib/contenttypes/fields.py @@ -1,4 +1,6 @@ import functools +import itertools +import operator from collections import defaultdict from django.contrib.contenttypes.models import ContentType @@ -566,19 +568,28 @@ def create_generic_related_manager(superclass, rel): queryset._add_hints(instance=instances[0]) queryset = queryset.using(queryset._db or self._db) - - query = { - '%s__pk' % self.content_type_field_name: self.content_type.id, - '%s__in' % self.object_id_field_name: {obj.pk for obj in instances} - } - + # Group instances by content types. + content_type_queries = ( + models.Q(**{ + '%s__pk' % self.content_type_field_name: content_type_id, + '%s__in' % self.object_id_field_name: {obj.pk for obj in objs} + }) + for content_type_id, objs in itertools.groupby( + sorted(instances, key=lambda obj: self.get_content_type(obj).pk), + lambda obj: self.get_content_type(obj).pk, + ) + ) + query = functools.reduce(operator.or_, content_type_queries) # We (possibly) need to convert object IDs to the type of the # instances' PK in order to match up instances: object_id_converter = instances[0]._meta.pk.to_python return ( - queryset.filter(**query), - lambda relobj: object_id_converter(getattr(relobj, self.object_id_field_name)), - lambda obj: obj.pk, + queryset.filter(query), + lambda relobj: ( + object_id_converter(getattr(relobj, self.object_id_field_name)), + relobj.content_type_id + ), + lambda obj: (obj.pk, self.get_content_type(obj).pk), False, self.prefetch_cache_name, False, |
