mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Revert "Fixed #16211 -- Added comparison and negation ops to F() expressions"
This reverts commit 28abf5f0eb.
Conflicts:
	docs/releases/1.5.txt
			
			
This commit is contained in:
		| @@ -913,9 +913,6 @@ class BaseDatabaseOperations(object): | ||||
|         can vary between backends (e.g., Oracle with %% and &) and between | ||||
|         subexpression types (e.g., date expressions) | ||||
|         """ | ||||
|         if connector == 'NOT': | ||||
|             assert len(sub_expressions) == 1 | ||||
|             return 'NOT (%s)' % sub_expressions[0] | ||||
|         conn = ' %s ' % connector | ||||
|         return conn.join(sub_expressions) | ||||
|  | ||||
|   | ||||
| @@ -18,17 +18,6 @@ class ExpressionNode(tree.Node): | ||||
|     AND = '&' | ||||
|     OR = '|' | ||||
|  | ||||
|     # Unary operator (needs special attention in combine_expression) | ||||
|     NOT = 'NOT' | ||||
|  | ||||
|     # Comparison operators | ||||
|     EQ = '=' | ||||
|     GE = '>=' | ||||
|     GT = '>' | ||||
|     LE = '<=' | ||||
|     LT = '<' | ||||
|     NE = '<>' | ||||
|  | ||||
|     def __init__(self, children=None, connector=None, negated=False): | ||||
|         if children is not None and len(children) > 1 and connector is None: | ||||
|             raise TypeError('You have to specify a connector.') | ||||
| @@ -104,32 +93,6 @@ class ExpressionNode(tree.Node): | ||||
|     def __ror__(self, other): | ||||
|         return self._combine(other, self.OR, True) | ||||
|  | ||||
|     def __invert__(self): | ||||
|         obj = ExpressionNode([self], connector=self.NOT, negated=True) | ||||
|         return obj | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         return self._combine(other, self.EQ, False) | ||||
|  | ||||
|     def __ge__(self, other): | ||||
|         return self._combine(other, self.GE, False) | ||||
|  | ||||
|     def __gt__(self, other): | ||||
|         return self._combine(other, self.GT, False) | ||||
|  | ||||
|     def __le__(self, other): | ||||
|         return self._combine(other, self.LE, False) | ||||
|  | ||||
|     def __lt__(self, other): | ||||
|         return self._combine(other, self.LT, False) | ||||
|  | ||||
|     def __ne__(self, other): | ||||
|         return self._combine(other, self.NE, False) | ||||
|  | ||||
|     def __bool__(self): | ||||
|         raise TypeError('Boolean operators should be avoided. Use bitwise operators.') | ||||
|     __nonzero__ = __bool__ | ||||
|  | ||||
|     def prepare_database_save(self, unused): | ||||
|         return self | ||||
|  | ||||
|   | ||||
| @@ -88,12 +88,8 @@ class Node(object): | ||||
|         Otherwise, the whole tree is pushed down one level and a new root | ||||
|         connector is created, connecting the existing tree and the new node. | ||||
|         """ | ||||
|         # Using for loop with 'is' instead of 'if node in children' so node | ||||
|         # __eq__ method doesn't get called. The __eq__ method can be overriden | ||||
|         # by subtypes, for example the F-expression. | ||||
|         for child in self.children: | ||||
|             if node is child and conn_type == self.connector: | ||||
|                 return | ||||
|         if node in self.children and conn_type == self.connector: | ||||
|             return | ||||
|         if len(self.children) < 2: | ||||
|             self.connector = conn_type | ||||
|         if self.connector == conn_type: | ||||
|   | ||||
| @@ -177,10 +177,6 @@ Django 1.5 also includes several smaller improvements worth noting: | ||||
|   :setting:`DEBUG` is `True` are sent to the console (unless you redefine the | ||||
|   logger in your :setting:`LOGGING` setting). | ||||
|  | ||||
| * :ref:`F() expressions <query-expressions>` now support comparison operations | ||||
|   and inversion, expanding the types of expressions that can be passed to the | ||||
|   database. | ||||
|  | ||||
| * When using :class:`~django.template.RequestContext`, it is now possible to | ||||
|   look up permissions by using ``{% if 'someapp.someperm' in perms %}`` | ||||
|   in templates. | ||||
|   | ||||
| @@ -640,15 +640,6 @@ that were modified more than 3 days after they were published:: | ||||
|     >>> from datetime import timedelta | ||||
|     >>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3)) | ||||
|  | ||||
| .. versionadded:: 1.5 | ||||
|     Comparisons and negation operators for ``F()`` expressions | ||||
|  | ||||
| Django also supports the comparison operators ``==``, ``!=``, ``<=``, ``<``, | ||||
| ``>``, ``>=`` and the bitwise negation operator ``~`` (boolean ``not`` operator | ||||
| will raise ``TypeError``):: | ||||
|  | ||||
|     >>> Entry.objects.filter(is_heavily_quoted=~(F('n_pingbacks') < 100)) | ||||
|  | ||||
| The pk lookup shortcut | ||||
| ---------------------- | ||||
|  | ||||
|   | ||||
| @@ -27,8 +27,6 @@ class Company(models.Model): | ||||
|         Employee, | ||||
|         related_name='company_point_of_contact_set', | ||||
|         null=True) | ||||
|     is_large = models.BooleanField( | ||||
|         blank=True) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|   | ||||
| @@ -11,22 +11,22 @@ from .models import Company, Employee | ||||
| class ExpressionsTests(TestCase): | ||||
|     def test_filter(self): | ||||
|         Company.objects.create( | ||||
|             name="Example Inc.", num_employees=2300, num_chairs=5, is_large=False, | ||||
|             name="Example Inc.", num_employees=2300, num_chairs=5, | ||||
|             ceo=Employee.objects.create(firstname="Joe", lastname="Smith") | ||||
|         ) | ||||
|         Company.objects.create( | ||||
|             name="Foobar Ltd.", num_employees=3, num_chairs=4, is_large=False, | ||||
|             name="Foobar Ltd.", num_employees=3, num_chairs=4, | ||||
|             ceo=Employee.objects.create(firstname="Frank", lastname="Meyer") | ||||
|         ) | ||||
|         Company.objects.create( | ||||
|             name="Test GmbH", num_employees=32, num_chairs=1, is_large=False, | ||||
|             name="Test GmbH", num_employees=32, num_chairs=1, | ||||
|             ceo=Employee.objects.create(firstname="Max", lastname="Mustermann") | ||||
|         ) | ||||
|  | ||||
|         company_query = Company.objects.values( | ||||
|             "name", "num_employees", "num_chairs", "is_large" | ||||
|             "name", "num_employees", "num_chairs" | ||||
|         ).order_by( | ||||
|             "name", "num_employees", "num_chairs", "is_large" | ||||
|             "name", "num_employees", "num_chairs" | ||||
|         ) | ||||
|  | ||||
|         # We can filter for companies where the number of employees is greater | ||||
| @@ -37,13 +37,11 @@ class ExpressionsTests(TestCase): | ||||
|                     "num_chairs": 5, | ||||
|                     "name": "Example Inc.", | ||||
|                     "num_employees": 2300, | ||||
|                     "is_large": False | ||||
|                 }, | ||||
|                 { | ||||
|                     "num_chairs": 1, | ||||
|                     "name": "Test GmbH", | ||||
|                     "num_employees": 32, | ||||
|                     "is_large": False | ||||
|                     "num_employees": 32 | ||||
|                 }, | ||||
|             ], | ||||
|             lambda o: o | ||||
| @@ -57,20 +55,17 @@ class ExpressionsTests(TestCase): | ||||
|                 { | ||||
|                     "num_chairs": 2300, | ||||
|                     "name": "Example Inc.", | ||||
|                     "num_employees": 2300, | ||||
|                     "is_large": False | ||||
|                     "num_employees": 2300 | ||||
|                 }, | ||||
|                 { | ||||
|                     "num_chairs": 3, | ||||
|                     "name": "Foobar Ltd.", | ||||
|                     "num_employees": 3, | ||||
|                     "is_large": False | ||||
|                     "num_employees": 3 | ||||
|                 }, | ||||
|                 { | ||||
|                     "num_chairs": 32, | ||||
|                     "name": "Test GmbH", | ||||
|                     "num_employees": 32, | ||||
|                     "is_large": False | ||||
|                     "num_employees": 32 | ||||
|                 } | ||||
|             ], | ||||
|             lambda o: o | ||||
| @@ -84,20 +79,17 @@ class ExpressionsTests(TestCase): | ||||
|                 { | ||||
|                     'num_chairs': 2302, | ||||
|                     'name': 'Example Inc.', | ||||
|                     'num_employees': 2300, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 2300 | ||||
|                 }, | ||||
|                 { | ||||
|                     'num_chairs': 5, | ||||
|                     'name': 'Foobar Ltd.', | ||||
|                     'num_employees': 3, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 3 | ||||
|                 }, | ||||
|                 { | ||||
|                     'num_chairs': 34, | ||||
|                     'name': 'Test GmbH', | ||||
|                     'num_employees': 32, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 32 | ||||
|                 } | ||||
|             ], | ||||
|             lambda o: o, | ||||
| @@ -112,20 +104,17 @@ class ExpressionsTests(TestCase): | ||||
|                 { | ||||
|                     'num_chairs': 6900, | ||||
|                     'name': 'Example Inc.', | ||||
|                     'num_employees': 2300, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 2300 | ||||
|                 }, | ||||
|                 { | ||||
|                     'num_chairs': 9, | ||||
|                     'name': 'Foobar Ltd.', | ||||
|                     'num_employees': 3, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 3 | ||||
|                 }, | ||||
|                 { | ||||
|                     'num_chairs': 96, | ||||
|                     'name': 'Test GmbH', | ||||
|                     'num_employees': 32, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 32 | ||||
|                 } | ||||
|             ], | ||||
|             lambda o: o, | ||||
| @@ -140,80 +129,21 @@ class ExpressionsTests(TestCase): | ||||
|                 { | ||||
|                     'num_chairs': 5294600, | ||||
|                     'name': 'Example Inc.', | ||||
|                     'num_employees': 2300, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 2300 | ||||
|                 }, | ||||
|                 { | ||||
|                     'num_chairs': 15, | ||||
|                     'name': 'Foobar Ltd.', | ||||
|                     'num_employees': 3, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 3 | ||||
|                 }, | ||||
|                 { | ||||
|                     'num_chairs': 1088, | ||||
|                     'name': 'Test GmbH', | ||||
|                     'num_employees': 32, | ||||
|                     'is_large': False | ||||
|                     'num_employees': 32 | ||||
|                 } | ||||
|             ], | ||||
|             lambda o: o, | ||||
|         ) | ||||
|         # The comparison operators and the bitwise unary not can be used | ||||
|         # to assign to boolean fields | ||||
|         for expression in ( | ||||
|             # Check boundaries | ||||
|             ~(F('num_employees') < 33), | ||||
|             ~(F('num_employees') <= 32), | ||||
|             (F('num_employees') > 2299), | ||||
|             (F('num_employees') >= 2300), | ||||
|             (F('num_employees') == 2300), | ||||
|             ((F('num_employees') + 1 != 4) & (32 != F('num_employees'))), | ||||
|             # Inverted argument order works too | ||||
|             (2299 < F('num_employees')), | ||||
|             (2300 <= F('num_employees')) | ||||
|         ): | ||||
|             # Test update by F-expression | ||||
|             company_query.update( | ||||
|                 is_large=expression | ||||
|             ) | ||||
|             # Compare results | ||||
|             self.assertQuerysetEqual( | ||||
|                 company_query, [ | ||||
|                     { | ||||
|                         'num_chairs': 5294600, | ||||
|                         'name': 'Example Inc.', | ||||
|                         'num_employees': 2300, | ||||
|                         'is_large': True | ||||
|                     }, | ||||
|                     { | ||||
|                         'num_chairs': 15, | ||||
|                         'name': 'Foobar Ltd.', | ||||
|                         'num_employees': 3, | ||||
|                         'is_large': False | ||||
|                     }, | ||||
|                     { | ||||
|                         'num_chairs': 1088, | ||||
|                         'name': 'Test GmbH', | ||||
|                         'num_employees': 32, | ||||
|                         'is_large': False | ||||
|                     } | ||||
|                 ], | ||||
|                 lambda o: o, | ||||
|             ) | ||||
|             # Reset values | ||||
|             company_query.update( | ||||
|                 is_large=False | ||||
|             ) | ||||
|  | ||||
|         # The python boolean operators should be avoided as they yield | ||||
|         # unexpected results | ||||
|         test_gmbh = Company.objects.get(name="Test GmbH") | ||||
|         with self.assertRaises(TypeError): | ||||
|             test_gmbh.is_large = not F('is_large') | ||||
|         with self.assertRaises(TypeError): | ||||
|             test_gmbh.is_large = F('is_large') and F('is_large') | ||||
|         with self.assertRaises(TypeError): | ||||
|             test_gmbh.is_large = F('is_large') or F('is_large') | ||||
|  | ||||
|         # The relation of a foreign key can become copied over to an other | ||||
|         # foreign key. | ||||
| @@ -272,8 +202,9 @@ class ExpressionsTests(TestCase): | ||||
|         test_gmbh.point_of_contact = None | ||||
|         test_gmbh.save() | ||||
|         self.assertTrue(test_gmbh.point_of_contact is None) | ||||
|         with self.assertRaises(ValueError): | ||||
|         def test(): | ||||
|             test_gmbh.point_of_contact = F("ceo") | ||||
|         self.assertRaises(ValueError, test) | ||||
|  | ||||
|         test_gmbh.point_of_contact = test_gmbh.ceo | ||||
|         test_gmbh.save() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user