mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Node.create() which has a compatible signature with Node.__init__() takes in a single `children` argument rather than relying in unpacking *args in Q.__init__() which calls Node.__init__(). In addition, we were often needing to unpack iterables into *args and can instead pass a list direct to Node.create().
This commit is contained in:
parent
845667f2d1
commit
9dff316be4
@ -527,7 +527,7 @@ class EmptyFieldListFilter(FieldListFilter):
|
|||||||
lookup_conditions.append((self.field_path, ""))
|
lookup_conditions.append((self.field_path, ""))
|
||||||
if self.field.null:
|
if self.field.null:
|
||||||
lookup_conditions.append((f"{self.field_path}__isnull", True))
|
lookup_conditions.append((f"{self.field_path}__isnull", True))
|
||||||
lookup_condition = models.Q(*lookup_conditions, _connector=models.Q.OR)
|
lookup_condition = models.Q.create(lookup_conditions, connector=models.Q.OR)
|
||||||
if self.lookup_val == "1":
|
if self.lookup_val == "1":
|
||||||
return queryset.filter(lookup_condition)
|
return queryset.filter(lookup_condition)
|
||||||
return queryset.exclude(lookup_condition)
|
return queryset.exclude(lookup_condition)
|
||||||
|
@ -1146,12 +1146,12 @@ class ModelAdmin(BaseModelAdmin):
|
|||||||
for bit in smart_split(search_term):
|
for bit in smart_split(search_term):
|
||||||
if bit.startswith(('"', "'")) and bit[0] == bit[-1]:
|
if bit.startswith(('"', "'")) and bit[0] == bit[-1]:
|
||||||
bit = unescape_string_literal(bit)
|
bit = unescape_string_literal(bit)
|
||||||
or_queries = models.Q(
|
or_queries = models.Q.create(
|
||||||
*((orm_lookup, bit) for orm_lookup in orm_lookups),
|
[(orm_lookup, bit) for orm_lookup in orm_lookups],
|
||||||
_connector=models.Q.OR,
|
connector=models.Q.OR,
|
||||||
)
|
)
|
||||||
term_queries.append(or_queries)
|
term_queries.append(or_queries)
|
||||||
queryset = queryset.filter(models.Q(*term_queries))
|
queryset = queryset.filter(models.Q.create(term_queries))
|
||||||
may_have_duplicates |= any(
|
may_have_duplicates |= any(
|
||||||
lookup_spawns_duplicates(self.opts, search_spec)
|
lookup_spawns_duplicates(self.opts, search_spec)
|
||||||
for search_spec in orm_lookups
|
for search_spec in orm_lookups
|
||||||
|
@ -627,17 +627,19 @@ def create_generic_related_manager(superclass, rel):
|
|||||||
queryset._add_hints(instance=instances[0])
|
queryset._add_hints(instance=instances[0])
|
||||||
queryset = queryset.using(queryset._db or self._db)
|
queryset = queryset.using(queryset._db or self._db)
|
||||||
# Group instances by content types.
|
# Group instances by content types.
|
||||||
content_type_queries = (
|
content_type_queries = [
|
||||||
models.Q(
|
models.Q.create(
|
||||||
(f"{self.content_type_field_name}__pk", content_type_id),
|
[
|
||||||
(f"{self.object_id_field_name}__in", {obj.pk for obj in objs}),
|
(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(
|
for content_type_id, objs in itertools.groupby(
|
||||||
sorted(instances, key=lambda obj: self.get_content_type(obj).pk),
|
sorted(instances, key=lambda obj: self.get_content_type(obj).pk),
|
||||||
lambda obj: self.get_content_type(obj).pk,
|
lambda obj: self.get_content_type(obj).pk,
|
||||||
)
|
)
|
||||||
)
|
]
|
||||||
query = models.Q(*content_type_queries, _connector=models.Q.OR)
|
query = models.Q.create(content_type_queries, connector=models.Q.OR)
|
||||||
# We (possibly) need to convert object IDs to the type of the
|
# We (possibly) need to convert object IDs to the type of the
|
||||||
# instances' PK in order to match up instances:
|
# instances' PK in order to match up instances:
|
||||||
object_id_converter = instances[0]._meta.pk.to_python
|
object_id_converter = instances[0]._meta.pk.to_python
|
||||||
|
@ -1152,8 +1152,8 @@ class Model(metaclass=ModelBase):
|
|||||||
op = "gt" if is_next else "lt"
|
op = "gt" if is_next else "lt"
|
||||||
order = "" if is_next else "-"
|
order = "" if is_next else "-"
|
||||||
param = getattr(self, field.attname)
|
param = getattr(self, field.attname)
|
||||||
q = Q((field.name, param), (f"pk__{op}", self.pk), _connector=Q.AND)
|
q = Q.create([(field.name, param), (f"pk__{op}", self.pk)], connector=Q.AND)
|
||||||
q = Q(q, (f"{field.name}__{op}", param), _connector=Q.OR)
|
q = Q.create([q, (f"{field.name}__{op}", param)], connector=Q.OR)
|
||||||
qs = (
|
qs = (
|
||||||
self.__class__._default_manager.using(self._state.db)
|
self.__class__._default_manager.using(self._state.db)
|
||||||
.filter(**kwargs)
|
.filter(**kwargs)
|
||||||
|
@ -399,9 +399,9 @@ class Collector:
|
|||||||
"""
|
"""
|
||||||
Get a QuerySet of the related model to objs via related fields.
|
Get a QuerySet of the related model to objs via related fields.
|
||||||
"""
|
"""
|
||||||
predicate = query_utils.Q(
|
predicate = query_utils.Q.create(
|
||||||
*((f"{related_field.name}__in", objs) for related_field in related_fields),
|
[(f"{related_field.name}__in", objs) for related_field in related_fields],
|
||||||
_connector=query_utils.Q.OR,
|
connector=query_utils.Q.OR,
|
||||||
)
|
)
|
||||||
return related_model._base_manager.using(self.using).filter(predicate)
|
return related_model._base_manager.using(self.using).filter(predicate)
|
||||||
|
|
||||||
|
@ -407,12 +407,13 @@ class RelatedField(FieldCacheMixin, Field):
|
|||||||
select all instances of self.related_field.model related through
|
select all instances of self.related_field.model related through
|
||||||
this field to obj. obj is an instance of self.model.
|
this field to obj. obj is an instance of self.model.
|
||||||
"""
|
"""
|
||||||
base_filter = (
|
base_q = Q.create(
|
||||||
(rh_field.attname, getattr(obj, lh_field.attname))
|
[
|
||||||
for lh_field, rh_field in self.related_fields
|
(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)
|
descriptor_filter = self.get_extra_descriptor_filter(obj)
|
||||||
base_q = Q(*base_filter)
|
|
||||||
if isinstance(descriptor_filter, dict):
|
if isinstance(descriptor_filter, dict):
|
||||||
return base_q & Q(**descriptor_filter)
|
return base_q & Q(**descriptor_filter)
|
||||||
elif descriptor_filter:
|
elif descriptor_filter:
|
||||||
|
@ -1002,19 +1002,21 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
|
|||||||
do_not_call_in_templates = True
|
do_not_call_in_templates = True
|
||||||
|
|
||||||
def _build_remove_filters(self, removed_vals):
|
def _build_remove_filters(self, removed_vals):
|
||||||
filters = Q((self.source_field_name, self.related_val))
|
filters = Q.create([(self.source_field_name, self.related_val)])
|
||||||
# No need to add a subquery condition if removed_vals is a QuerySet without
|
# No need to add a subquery condition if removed_vals is a QuerySet without
|
||||||
# filters.
|
# filters.
|
||||||
removed_vals_filters = (
|
removed_vals_filters = (
|
||||||
not isinstance(removed_vals, QuerySet) or removed_vals._has_filters()
|
not isinstance(removed_vals, QuerySet) or removed_vals._has_filters()
|
||||||
)
|
)
|
||||||
if removed_vals_filters:
|
if removed_vals_filters:
|
||||||
filters &= Q((f"{self.target_field_name}__in", removed_vals))
|
filters &= Q.create([(f"{self.target_field_name}__in", removed_vals)])
|
||||||
if self.symmetrical:
|
if self.symmetrical:
|
||||||
symmetrical_filters = Q((self.target_field_name, self.related_val))
|
symmetrical_filters = Q.create(
|
||||||
|
[(self.target_field_name, self.related_val)]
|
||||||
|
)
|
||||||
if removed_vals_filters:
|
if removed_vals_filters:
|
||||||
symmetrical_filters &= Q(
|
symmetrical_filters &= Q.create(
|
||||||
(f"{self.source_field_name}__in", removed_vals)
|
[(f"{self.source_field_name}__in", removed_vals)]
|
||||||
)
|
)
|
||||||
filters |= symmetrical_filters
|
filters |= symmetrical_filters
|
||||||
return filters
|
return filters
|
||||||
|
@ -33,7 +33,7 @@ class Node:
|
|||||||
__init__() with a signature that conflicts with the one defined in
|
__init__() with a signature that conflicts with the one defined in
|
||||||
Node.__init__().
|
Node.__init__().
|
||||||
"""
|
"""
|
||||||
obj = Node(children, connector, negated)
|
obj = Node(children, connector or cls.default, negated)
|
||||||
obj.__class__ = cls
|
obj.__class__ = cls
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
@ -216,6 +216,15 @@ class QTests(SimpleTestCase):
|
|||||||
flatten = list(q.flatten())
|
flatten = list(q.flatten())
|
||||||
self.assertEqual(len(flatten), 7)
|
self.assertEqual(len(flatten), 7)
|
||||||
|
|
||||||
|
def test_create_helper(self):
|
||||||
|
items = [("a", 1), ("b", 2), ("c", 3)]
|
||||||
|
for connector in [Q.AND, Q.OR, Q.XOR]:
|
||||||
|
with self.subTest(connector=connector):
|
||||||
|
self.assertEqual(
|
||||||
|
Q.create(items, connector=connector),
|
||||||
|
Q(*items, _connector=connector),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class QCheckTests(TestCase):
|
class QCheckTests(TestCase):
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user