From 73dc570e13f9e96f4fa9752fd52f611fa3f334dd Mon Sep 17 00:00:00 2001
From: Nate Bragg <jonathan.bragg@alum.rpi.edu>
Date: Wed, 18 Jan 2012 22:02:12 -0500
Subject: [PATCH] Implemented a fix to #17186 using a negation node
---
django/db/models/expressions.py | 14 ++++++++++++++
tests/modeltests/expressions/models.py | 3 +++
tests/modeltests/expressions/tests.py | 10 ++++++++++
3 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py
index a71f4a3..7c978dc 100644
a
|
b
|
class ExpressionNode(tree.Node):
|
70 | 70 | def __or__(self, other): |
71 | 71 | return self._combine(other, self.OR, False) |
72 | 72 | |
| 73 | def __invert__(self): |
| 74 | return NotNode([self]) |
| 75 | |
73 | 76 | def __radd__(self, other): |
74 | 77 | return self._combine(other, self.ADD, True) |
75 | 78 | |
… |
… |
class F(ExpressionNode):
|
113 | 116 | def evaluate(self, evaluator, qn, connection): |
114 | 117 | return evaluator.evaluate_leaf(self, qn, connection) |
115 | 118 | |
| 119 | class NotNode(ExpressionNode): |
| 120 | """ |
| 121 | Node that represents a negation. |
| 122 | """ |
| 123 | def __init__(self, children=None): |
| 124 | super(NotNode, self).__init__(children, None, True) |
| 125 | |
| 126 | def evaluate(self, evaluator, qn, connection): |
| 127 | sql, params = evaluator.evaluate_node(self, qn, connection) |
| 128 | return ("NOT %s" % sql, params) |
| 129 | |
116 | 130 | class DateModifierNode(ExpressionNode): |
117 | 131 | """ |
118 | 132 | Node that implements the following syntax: |
diff --git a/tests/modeltests/expressions/models.py b/tests/modeltests/expressions/models.py
index dd50499..da6f1df 100644
a
|
b
|
from django.db import models
|
8 | 8 | class Employee(models.Model): |
9 | 9 | firstname = models.CharField(max_length=50) |
10 | 10 | lastname = models.CharField(max_length=50) |
| 11 | is_active = models.BooleanField(default=False) |
11 | 12 | |
12 | 13 | def __unicode__(self): |
13 | 14 | return u'%s %s' % (self.firstname, self.lastname) |
… |
… |
class Company(models.Model):
|
26 | 27 | |
27 | 28 | def __unicode__(self): |
28 | 29 | return self.name |
| 30 | |
| 31 | |
diff --git a/tests/modeltests/expressions/tests.py b/tests/modeltests/expressions/tests.py
index 8f4f546..59ae91b 100644
a
|
b
|
class ExpressionsTests(TestCase):
|
22 | 22 | ceo=Employee.objects.create(firstname="Max", lastname="Mustermann") |
23 | 23 | ) |
24 | 24 | |
| 25 | # mark acttive employees when their companys have num_chairs great that 3 |
| 26 | employee_qs = Employee.objects.filter(is_active=False) |
| 27 | self.assertEqual(employee_qs.count(), 3) |
| 28 | |
| 29 | Employee.objects.filter(company_ceo_set__num_chairs__gte=3)\ |
| 30 | .update(is_active=~F("is_active")) |
| 31 | |
| 32 | employee_qs = Employee.objects.filter(is_active=False) |
| 33 | self.assertEqual(employee_qs.count(), 1) |
| 34 | |
25 | 35 | company_query = Company.objects.values( |
26 | 36 | "name", "num_employees", "num_chairs" |
27 | 37 | ).order_by( |