summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHasan Ramezani <hasan.r67@gmail.com>2020-07-28 13:56:39 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-07-29 08:20:58 +0200
commit9c9a3fe1180fc92fbd4c3302dbe0b3e083bf0381 (patch)
treef3497614127fe35854556086a4182998b05f3878
parentb6dfdaff33f19757b1cb9b3bf1d17f28b94859d4 (diff)
Fixed #31783 -- Fixed crash when filtering againts "negate" field.
Thanks Simon Charette for the initial patch.
-rw-r--r--django/db/models/query.py14
-rw-r--r--tests/queries/models.py1
-rw-r--r--tests/queries/tests.py9
3 files changed, 16 insertions, 8 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 07d6ffd4ca..d655ede8d9 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -204,7 +204,7 @@ class QuerySet:
def query(self):
if self._deferred_filter:
negate, args, kwargs = self._deferred_filter
- self._filter_or_exclude_inplace(negate, *args, **kwargs)
+ self._filter_or_exclude_inplace(negate, args, kwargs)
self._deferred_filter = None
return self._query
@@ -939,7 +939,7 @@ class QuerySet:
set.
"""
self._not_support_combined_queries('filter')
- return self._filter_or_exclude(False, *args, **kwargs)
+ return self._filter_or_exclude(False, args, kwargs)
def exclude(self, *args, **kwargs):
"""
@@ -947,9 +947,9 @@ class QuerySet:
set.
"""
self._not_support_combined_queries('exclude')
- return self._filter_or_exclude(True, *args, **kwargs)
+ return self._filter_or_exclude(True, args, kwargs)
- def _filter_or_exclude(self, negate, *args, **kwargs):
+ def _filter_or_exclude(self, negate, args, kwargs):
if args or kwargs:
assert not self.query.is_sliced, \
"Cannot filter a query once a slice has been taken."
@@ -959,10 +959,10 @@ class QuerySet:
self._defer_next_filter = False
clone._deferred_filter = negate, args, kwargs
else:
- clone._filter_or_exclude_inplace(negate, *args, **kwargs)
+ clone._filter_or_exclude_inplace(negate, args, kwargs)
return clone
- def _filter_or_exclude_inplace(self, negate, *args, **kwargs):
+ def _filter_or_exclude_inplace(self, negate, args, kwargs):
if negate:
self._query.add_q(~Q(*args, **kwargs))
else:
@@ -983,7 +983,7 @@ class QuerySet:
clone.query.add_q(filter_obj)
return clone
else:
- return self._filter_or_exclude(False, **filter_obj)
+ return self._filter_or_exclude(False, args=(), kwargs=filter_obj)
def _combinator_query(self, combinator, *other_qs, all=False):
# Clone the query to inherit the select list and everything
diff --git a/tests/queries/models.py b/tests/queries/models.py
index a4f6245aa8..a5faa2a84b 100644
--- a/tests/queries/models.py
+++ b/tests/queries/models.py
@@ -42,6 +42,7 @@ class Note(models.Model):
note = models.CharField(max_length=100)
misc = models.CharField(max_length=10)
tag = models.ForeignKey(Tag, models.SET_NULL, blank=True, null=True)
+ negate = models.BooleanField(default=True)
class Meta:
ordering = ['note']
diff --git a/tests/queries/tests.py b/tests/queries/tests.py
index 2863cfb568..f9a57b088a 100644
--- a/tests/queries/tests.py
+++ b/tests/queries/tests.py
@@ -47,7 +47,7 @@ class Queries1Tests(TestCase):
cls.n1 = Note.objects.create(note='n1', misc='foo', id=1)
cls.n2 = Note.objects.create(note='n2', misc='bar', id=2)
- cls.n3 = Note.objects.create(note='n3', misc='foo', id=3)
+ cls.n3 = Note.objects.create(note='n3', misc='foo', id=3, negate=False)
ann1 = Annotation.objects.create(name='a1', tag=cls.t1)
ann1.notes.add(cls.n1)
@@ -1216,6 +1216,13 @@ class Queries1Tests(TestCase):
[self.a3, self.a4],
)
+ def test_negate_field(self):
+ self.assertSequenceEqual(
+ Note.objects.filter(negate=True),
+ [self.n1, self.n2],
+ )
+ self.assertSequenceEqual(Note.objects.exclude(negate=True), [self.n3])
+
class Queries2Tests(TestCase):
@classmethod