Ticket #16211: issue16211-query-expression-logical-operators.patch
File issue16211-query-expression-logical-operators.patch, 9.9 KB (added by , 13 years ago) |
---|
-
django/db/models/expressions.py
18 18 AND = '&' 19 19 OR = '|' 20 20 21 # Logical operators 22 NOT = 'NOT' # unary, needs special attention in combine_expression 23 EQ = '=' 24 GE = '>=' 25 GT = '>' 26 LE = '<=' 27 LT = '<' 28 NE = '<>' 29 21 30 def __init__(self, children=None, connector=None, negated=False): 22 31 if children is not None and len(children) > 1 and connector is None: 23 32 raise TypeError('You have to specify a connector.') … … 91 100 def __ror__(self, other): 92 101 return self._combine(other, self.OR, True) 93 102 103 def __invert__(self): 104 obj = ExpressionNode([self], connector=self.NOT, negated=True) 105 return obj 106 107 def __eq__(self, other): 108 return self._combine(other, self.EQ, False) 109 110 def __ge__(self, other): 111 return self._combine(other, self.GE, False) 112 113 def __gt__(self, other): 114 return self._combine(other, self.GT, False) 115 116 def __le__(self, other): 117 return self._combine(other, self.LE, False) 118 119 def __lt__(self, other): 120 return self._combine(other, self.LT, False) 121 122 def __ne__(self, other): 123 return self._combine(other, self.NE, False) 124 94 125 def prepare_database_save(self, unused): 95 126 return self 96 127 -
django/db/backends/__init__.py
771 771 can vary between backends (e.g., Oracle with %% and &) and between 772 772 subexpression types (e.g., date expressions) 773 773 """ 774 if connector == 'NOT': 775 assert len(sub_expressions) == 1 776 return 'NOT (%s)' % sub_expressions[0] 774 777 conn = ' %s ' % connector 775 778 return conn.join(sub_expressions) 776 779 -
django/utils/tree.py
87 87 Otherwise, the whole tree is pushed down one level and a new root 88 88 connector is created, connecting the existing tree and the new node. 89 89 """ 90 if node in self.children and conn_type == self.connector: 91 return 90 # Using for loop with 'is' instead of 'if node in children' so node 91 # __eq__ method doesn't get called 92 for child in self.children: 93 if node is child and conn_type == self.connector: 94 return 92 95 if len(self.children) < 2: 93 96 self.connector = conn_type 94 97 if self.connector == conn_type: -
tests/modeltests/expressions/tests.py
8 8 class ExpressionsTests(TestCase): 9 9 def test_filter(self): 10 10 Company.objects.create( 11 name="Example Inc.", num_employees=2300, num_chairs=5, 11 name="Example Inc.", num_employees=2300, num_chairs=5, is_large=False, 12 12 ceo=Employee.objects.create(firstname="Joe", lastname="Smith") 13 13 ) 14 14 Company.objects.create( 15 name="Foobar Ltd.", num_employees=3, num_chairs=4, 15 name="Foobar Ltd.", num_employees=3, num_chairs=4, is_large=False, 16 16 ceo=Employee.objects.create(firstname="Frank", lastname="Meyer") 17 17 ) 18 18 Company.objects.create( 19 name="Test GmbH", num_employees=32, num_chairs=1, 19 name="Test GmbH", num_employees=32, num_chairs=1, is_large=False, 20 20 ceo=Employee.objects.create(firstname="Max", lastname="Mustermann") 21 21 ) 22 22 23 23 company_query = Company.objects.values( 24 "name", "num_employees", "num_chairs" 24 "name", "num_employees", "num_chairs", "is_large" 25 25 ).order_by( 26 "name", "num_employees", "num_chairs" 26 "name", "num_employees", "num_chairs", "is_large" 27 27 ) 28 28 29 29 # We can filter for companies where the number of employees is greater … … 34 34 "num_chairs": 5, 35 35 "name": "Example Inc.", 36 36 "num_employees": 2300, 37 "is_large": False 37 38 }, 38 39 { 39 40 "num_chairs": 1, 40 41 "name": "Test GmbH", 41 "num_employees": 32 42 "num_employees": 32, 43 "is_large": False 42 44 }, 43 45 ], 44 46 lambda o: o … … 52 54 { 53 55 "num_chairs": 2300, 54 56 "name": "Example Inc.", 55 "num_employees": 2300 57 "num_employees": 2300, 58 "is_large": False 56 59 }, 57 60 { 58 61 "num_chairs": 3, 59 62 "name": "Foobar Ltd.", 60 "num_employees": 3 63 "num_employees": 3, 64 "is_large": False 61 65 }, 62 66 { 63 67 "num_chairs": 32, 64 68 "name": "Test GmbH", 65 "num_employees": 32 69 "num_employees": 32, 70 "is_large": False 66 71 } 67 72 ], 68 73 lambda o: o … … 76 81 { 77 82 'num_chairs': 2302, 78 83 'name': u'Example Inc.', 79 'num_employees': 2300 84 'num_employees': 2300, 85 'is_large': False 80 86 }, 81 87 { 82 88 'num_chairs': 5, 83 89 'name': u'Foobar Ltd.', 84 'num_employees': 3 90 'num_employees': 3, 91 'is_large': False 85 92 }, 86 93 { 87 94 'num_chairs': 34, 88 95 'name': u'Test GmbH', 89 'num_employees': 32 96 'num_employees': 32, 97 'is_large': False 90 98 } 91 99 ], 92 100 lambda o: o, … … 101 109 { 102 110 'num_chairs': 6900, 103 111 'name': u'Example Inc.', 104 'num_employees': 2300 112 'num_employees': 2300, 113 'is_large': False 105 114 }, 106 115 { 107 116 'num_chairs': 9, 108 117 'name': u'Foobar Ltd.', 109 'num_employees': 3 118 'num_employees': 3, 119 'is_large': False 110 120 }, 111 121 { 112 122 'num_chairs': 96, 113 123 'name': u'Test GmbH', 114 'num_employees': 32 124 'num_employees': 32, 125 'is_large': False 115 126 } 116 127 ], 117 128 lambda o: o, … … 126 137 { 127 138 'num_chairs': 5294600, 128 139 'name': u'Example Inc.', 129 'num_employees': 2300 140 'num_employees': 2300, 141 'is_large': False 130 142 }, 131 143 { 132 144 'num_chairs': 15, 133 145 'name': u'Foobar Ltd.', 134 'num_employees': 3 146 'num_employees': 3, 147 'is_large': False 135 148 }, 136 149 { 137 150 'num_chairs': 1088, 138 151 'name': u'Test GmbH', 139 'num_employees': 32 152 'num_employees': 32, 153 'is_large': False 140 154 } 141 155 ], 142 156 lambda o: o, 143 157 ) 144 158 159 # The logical operators (including a unary not) can be used to assign 160 # to boolean fields 161 for expression in ( 162 # Check boundaries 163 ~(F('num_employees') < 33), 164 ~(F('num_employees') <= 32), 165 (F('num_employees') > 2299), 166 (F('num_employees') >= 2300), 167 (F('num_employees') == 2300), 168 ((F('num_employees') != 3) & (32 != F('num_employees'))), 169 # Inverted argument order works too 170 (2299 < F('num_employees')), 171 (2300 <= F('num_employees')) 172 ): 173 company_query.update( 174 is_large=expression 175 ) 176 self.assertQuerysetEqual( 177 company_query, [ 178 { 179 'num_chairs': 5294600, 180 'name': u'Example Inc.', 181 'num_employees': 2300, 182 'is_large': True 183 }, 184 { 185 'num_chairs': 15, 186 'name': u'Foobar Ltd.', 187 'num_employees': 3, 188 'is_large': False 189 }, 190 { 191 'num_chairs': 1088, 192 'name': u'Test GmbH', 193 'num_employees': 32, 194 'is_large': False 195 } 196 ], 197 lambda o: o, 198 ) 199 145 200 # The relation of a foreign key can become copied over to an other 146 201 # foreign key. 147 202 self.assertEqual( -
tests/modeltests/expressions/models.py
22 22 Employee, 23 23 related_name='company_point_of_contact_set', 24 24 null=True) 25 is_large = models.BooleanField( 26 blank=True) 25 27 26 28 def __unicode__(self): 27 29 return self.name