summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeryn Knight <keryn@kerynknight.com>2021-07-28 09:16:06 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-07-28 09:38:46 +0200
commit9662193aea2ee982bc8e553c62499aca5e606755 (patch)
tree6e9a63c142f940b77f79b04b3b57f66e8e75a3fd
parent5b8ef8aa5b746d96d6558efd6bc119f347002703 (diff)
Refs #32946 -- Changed internal usage of dynamic Q() objects construction to use non-kwargs initialization.
This prefers non-kwargs construction of dynamically generated Q() objects to create a single Q() object instead of many and then combining them, where possible.
-rw-r--r--django/contrib/admin/filters.py7
-rw-r--r--django/contrib/admin/options.py11
-rw-r--r--django/contrib/contenttypes/fields.py11
-rw-r--r--django/db/models/base.py4
-rw-r--r--django/db/models/deletion.py14
-rw-r--r--django/db/models/fields/related.py8
-rw-r--r--django/db/models/fields/related_descriptors.py9
7 files changed, 33 insertions, 31 deletions
diff --git a/django/contrib/admin/filters.py b/django/contrib/admin/filters.py
index 7f4690806b..82dabe4d2c 100644
--- a/django/contrib/admin/filters.py
+++ b/django/contrib/admin/filters.py
@@ -451,11 +451,12 @@ class EmptyFieldListFilter(FieldListFilter):
if self.lookup_val not in ('0', '1'):
raise IncorrectLookupParameters
- lookup_condition = models.Q()
+ lookup_conditions = []
if self.field.empty_strings_allowed:
- lookup_condition |= models.Q(**{self.field_path: ''})
+ lookup_conditions.append((self.field_path, ''))
if self.field.null:
- lookup_condition |= models.Q(**{'%s__isnull' % self.field_path: True})
+ lookup_conditions.append((f'{self.field_path}__isnull', True))
+ lookup_condition = models.Q(*lookup_conditions, _connector=models.Q.OR)
if self.lookup_val == '1':
return queryset.filter(lookup_condition)
return queryset.exclude(lookup_condition)
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 7a5551f650..dadd4acfa1 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -1,8 +1,7 @@
import copy
import json
-import operator
import re
-from functools import partial, reduce, update_wrapper
+from functools import partial, update_wrapper
from urllib.parse import quote as urlquote
from django import forms
@@ -1035,9 +1034,11 @@ class ModelAdmin(BaseModelAdmin):
for bit in smart_split(search_term):
if bit.startswith(('"', "'")) and bit[0] == bit[-1]:
bit = unescape_string_literal(bit)
- or_queries = [models.Q(**{orm_lookup: bit})
- for orm_lookup in orm_lookups]
- queryset = queryset.filter(reduce(operator.or_, or_queries))
+ or_queries = models.Q(
+ *((orm_lookup, bit) for orm_lookup in orm_lookups),
+ _connector=models.Q.OR,
+ )
+ queryset = queryset.filter(or_queries)
may_have_duplicates |= any(
lookup_spawns_duplicates(self.opts, search_spec)
for search_spec in orm_lookups
diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py
index 4346e01785..fbd55606ae 100644
--- a/django/contrib/contenttypes/fields.py
+++ b/django/contrib/contenttypes/fields.py
@@ -1,6 +1,5 @@
import functools
import itertools
-import operator
from collections import defaultdict
from django.contrib.contenttypes.models import ContentType
@@ -571,16 +570,16 @@ def create_generic_related_manager(superclass, rel):
queryset = queryset.using(queryset._db or self._db)
# 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}
- })
+ models.Q(
+ (f'{self.content_type_field_name}__pk', content_type_id),
+ (f'{self.object_id_field_name}__in', {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)
+ query = models.Q(*content_type_queries, _connector=models.Q.OR)
# 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
diff --git a/django/db/models/base.py b/django/db/models/base.py
index f208067aae..3c46afcf9f 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -971,8 +971,8 @@ class Model(metaclass=ModelBase):
op = 'gt' if is_next else 'lt'
order = '' if is_next else '-'
param = getattr(self, field.attname)
- q = Q(**{'%s__%s' % (field.name, op): param})
- q = q | Q(**{field.name: param, 'pk__%s' % op: self.pk})
+ q = Q((field.name, param), (f'pk__{op}', self.pk), _connector=Q.AND)
+ q = Q(q, (f'{field.name}__{op}', param), _connector=Q.OR)
qs = self.__class__._default_manager.using(self._state.db).filter(**kwargs).filter(q).order_by(
'%s%s' % (order, field.name), '%spk' % order
)
diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 0493b0e1e2..d8d8b25990 100644
--- a/django/db/models/deletion.py
+++ b/django/db/models/deletion.py
@@ -1,6 +1,5 @@
-import operator
from collections import Counter, defaultdict
-from functools import partial, reduce
+from functools import partial
from itertools import chain
from operator import attrgetter
@@ -347,10 +346,13 @@ class Collector:
"""
Get a QuerySet of the related model to objs via related fields.
"""
- predicate = reduce(operator.or_, (
- query_utils.Q(**{'%s__in' % related_field.name: objs})
- for related_field in related_fields
- ))
+ predicate = query_utils.Q(
+ *(
+ (f'{related_field.name}__in', objs)
+ for related_field in related_fields
+ ),
+ _connector=query_utils.Q.OR,
+ )
return related_model._base_manager.using(self.using).filter(predicate)
def instances_with_model(self):
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index ac45127fde..febaadbb5b 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -359,12 +359,12 @@ class RelatedField(FieldCacheMixin, Field):
select all instances of self.related_field.model related through
this field to obj. obj is an instance of self.model.
"""
- base_filter = {
- rh_field.attname: getattr(obj, lh_field.attname)
+ base_filter = (
+ (rh_field.attname, getattr(obj, lh_field.attname))
for lh_field, rh_field in self.related_fields
- }
+ )
descriptor_filter = self.get_extra_descriptor_filter(obj)
- base_q = Q(**base_filter)
+ base_q = Q(*base_filter)
if isinstance(descriptor_filter, dict):
return base_q & Q(**descriptor_filter)
elif descriptor_filter:
diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py
index 872a4c98dc..dba9e14c86 100644
--- a/django/db/models/fields/related_descriptors.py
+++ b/django/db/models/fields/related_descriptors.py
@@ -866,18 +866,17 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
do_not_call_in_templates = True
def _build_remove_filters(self, removed_vals):
- filters = Q(**{self.source_field_name: self.related_val})
+ filters = Q((self.source_field_name, self.related_val))
# No need to add a subquery condition if removed_vals is a QuerySet without
# filters.
removed_vals_filters = (not isinstance(removed_vals, QuerySet) or
removed_vals._has_filters())
if removed_vals_filters:
- filters &= Q(**{'%s__in' % self.target_field_name: removed_vals})
+ filters &= Q((f'{self.target_field_name}__in', removed_vals))
if self.symmetrical:
- symmetrical_filters = Q(**{self.target_field_name: self.related_val})
+ symmetrical_filters = Q((self.target_field_name, self.related_val))
if removed_vals_filters:
- symmetrical_filters &= Q(
- **{'%s__in' % self.source_field_name: removed_vals})
+ symmetrical_filters &= Q((f'{self.source_field_name}__in', removed_vals))
filters |= symmetrical_filters
return filters