Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

queryset-refactor: Added ~ support to Q-objects. Based heavily on a p…

…atch from

Collin Grady. Refs #4858.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6518 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit a3b22d9db07ab21bda752f765b0a4414c73dee57 1 parent f74464d
@malcolmt malcolmt authored
View
6 django/db/models/query_utils.py
@@ -40,6 +40,9 @@ def __or__(self, other):
def __and__(self, other):
return self._combine(other, self.AND)
+ def __invert__(self):
+ return QNot(self)
+
class QNot(Q):
"""
Encapsulates the negation of a Q object.
@@ -50,3 +53,6 @@ def __init__(self, q):
self.add(q, self.AND)
self.negate()
+ def __invert__(self):
+ return self.children[0]
+
View
14 docs/db-api.txt
@@ -211,11 +211,11 @@ Saving ForeignKey and ManyToManyField fields
--------------------------------------------
Updating ``ForeignKey`` fields works exactly the same way as saving a normal
-field; simply assign an object of the right type to the field in question::
+field; simply assign an object of the right type to the field in question::
- cheese_blog = Blog.objects.get(name="Cheddar Talk")
- entry.blog = cheese_blog
- entry.save()
+ cheese_blog = Blog.objects.get(name="Cheddar Talk")
+ entry.blog = cheese_blog
+ entry.save()
Updating a ``ManyToManyField`` works a little differently; use the ``add()``
method on the field to add a record to the relation::
@@ -1563,6 +1563,12 @@ This is equivalent to the following SQL ``WHERE`` clause::
You can compose statements of arbitrary complexity by combining ``Q`` objects
with the ``&`` and ``|`` operators. You can also use parenthetical grouping.
+``Q`` objects can also be negated using the ``~`` operator, allowing for
+combined lookups that combine both a normal query and a negated (``NOT``)
+query::
+
+ Q(question__startswith='Who') | ~Q(pub_date__year=2005)
+
Each lookup function that takes keyword-arguments (e.g. ``filter()``,
``exclude()``, ``get()``) can also be passed one or more ``Q`` objects as
positional (not-named) arguments. If you provide multiple ``Q`` object
View
11 tests/modeltests/or_lookups/models.py
@@ -90,6 +90,17 @@ def __unicode__(self):
>>> Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello')
[<Article: Hello and goodbye>]
+# Q objects can be negated
+>>> Article.objects.filter(Q(pk=1) | ~Q(pk=2))
+[<Article: Hello>, <Article: Hello and goodbye>]
+>>> Article.objects.filter(~Q(pk=1) & ~Q(pk=2))
+[<Article: Hello and goodbye>]
+
+# This allows for more complex queries than filter() and exclude() alone would
+# allow
+>>> Article.objects.filter(Q(pk=1) & (~Q(pk=2) | Q(pk=3)))
+[<Article: Hello>]
+
# Try some arg queries with operations other than get_list
>>> Article.objects.get(Q(headline__startswith='Hello'), Q(headline__contains='bye'))
<Article: Hello and goodbye>

0 comments on commit a3b22d9

Please sign in to comment.
Something went wrong with that request. Please try again.