Moved F() '&' and '|' to .bitand() and .bitor()
Done for consistency with Q() expressions and QuerySet combining. This will allow usage of '&' and '|' as boolean logical operators in the future. Refs #16211.
This commit is contained in:
parent
a8b1861fc4
commit
b625e8272b
|
@ -14,9 +14,11 @@ class ExpressionNode(tree.Node):
|
||||||
# because it can be used in strings that also
|
# because it can be used in strings that also
|
||||||
# have parameter substitution.
|
# have parameter substitution.
|
||||||
|
|
||||||
# Bitwise operators
|
# Bitwise operators - note that these are generated by .bitand()
|
||||||
AND = '&'
|
# and .bitor(), the '&' and '|' are reserved for boolean operator
|
||||||
OR = '|'
|
# usage.
|
||||||
|
BITAND = '&'
|
||||||
|
BITOR = '|'
|
||||||
|
|
||||||
def __init__(self, children=None, connector=None, negated=False):
|
def __init__(self, children=None, connector=None, negated=False):
|
||||||
if children is not None and len(children) > 1 and connector is None:
|
if children is not None and len(children) > 1 and connector is None:
|
||||||
|
@ -66,10 +68,20 @@ class ExpressionNode(tree.Node):
|
||||||
return self._combine(other, self.MOD, False)
|
return self._combine(other, self.MOD, False)
|
||||||
|
|
||||||
def __and__(self, other):
|
def __and__(self, other):
|
||||||
return self._combine(other, self.AND, False)
|
raise NotImplementedError(
|
||||||
|
"Use .bitand() and .bitor() for bitwise logical operations."
|
||||||
|
)
|
||||||
|
|
||||||
|
def bitand(self, other):
|
||||||
|
return self._combine(other, self.BITAND, False)
|
||||||
|
|
||||||
def __or__(self, other):
|
def __or__(self, other):
|
||||||
return self._combine(other, self.OR, False)
|
raise NotImplementedError(
|
||||||
|
"Use .bitand() and .bitor() for bitwise logical operations."
|
||||||
|
)
|
||||||
|
|
||||||
|
def bitor(self, other):
|
||||||
|
return self._combine(other, self.BITOR, False)
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other):
|
||||||
return self._combine(other, self.ADD, True)
|
return self._combine(other, self.ADD, True)
|
||||||
|
@ -88,10 +100,14 @@ class ExpressionNode(tree.Node):
|
||||||
return self._combine(other, self.MOD, True)
|
return self._combine(other, self.MOD, True)
|
||||||
|
|
||||||
def __rand__(self, other):
|
def __rand__(self, other):
|
||||||
return self._combine(other, self.AND, True)
|
raise NotImplementedError(
|
||||||
|
"Use .bitand() and .bitor() for bitwise logical operations."
|
||||||
|
)
|
||||||
|
|
||||||
def __ror__(self, other):
|
def __ror__(self, other):
|
||||||
return self._combine(other, self.OR, True)
|
raise NotImplementedError(
|
||||||
|
"Use .bitand() and .bitor() for bitwise logical operations."
|
||||||
|
)
|
||||||
|
|
||||||
def prepare_database_save(self, unused):
|
def prepare_database_save(self, unused):
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -438,6 +438,12 @@ Miscellaneous
|
||||||
needs. The new default value is `0666` (octal) and the current umask value
|
needs. The new default value is `0666` (octal) and the current umask value
|
||||||
is first masked out.
|
is first masked out.
|
||||||
|
|
||||||
|
* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
|
||||||
|
``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
||||||
|
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
|
||||||
|
:ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
|
||||||
|
the operators are used as boolean AND and OR operators.
|
||||||
|
|
||||||
Features deprecated in 1.5
|
Features deprecated in 1.5
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
|
|
@ -640,6 +640,18 @@ that were modified more than 3 days after they were published::
|
||||||
>>> from datetime import timedelta
|
>>> from datetime import timedelta
|
||||||
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
|
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
|
||||||
|
|
||||||
|
.. versionadded:: 1.5
|
||||||
|
``.bitand()`` and ``.bitor()``
|
||||||
|
|
||||||
|
The ``F()`` objects now support bitwise operations by ``.bitand()`` and
|
||||||
|
``.bitor()``, for example::
|
||||||
|
|
||||||
|
>>> F('somefield').bitand(16)
|
||||||
|
|
||||||
|
.. versionchanged:: 1.5
|
||||||
|
The previously undocumented operators ``&`` and ``|`` no longer produce
|
||||||
|
bitwise operations, use ``.bitand()`` and ``.bitor()`` instead.
|
||||||
|
|
||||||
The pk lookup shortcut
|
The pk lookup shortcut
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ class ExpressionOperatorTests(TestCase):
|
||||||
|
|
||||||
def test_lefthand_bitwise_and(self):
|
def test_lefthand_bitwise_and(self):
|
||||||
# LH Bitwise ands on integers
|
# LH Bitwise ands on integers
|
||||||
Number.objects.filter(pk=self.n.pk).update(integer=F('integer') & 56)
|
Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitand(56))
|
||||||
|
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40)
|
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40)
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||||
|
@ -136,7 +136,7 @@ class ExpressionOperatorTests(TestCase):
|
||||||
@skipUnlessDBFeature('supports_bitwise_or')
|
@skipUnlessDBFeature('supports_bitwise_or')
|
||||||
def test_lefthand_bitwise_or(self):
|
def test_lefthand_bitwise_or(self):
|
||||||
# LH Bitwise or on integers
|
# LH Bitwise or on integers
|
||||||
Number.objects.filter(pk=self.n.pk).update(integer=F('integer') | 48)
|
Number.objects.filter(pk=self.n.pk).update(integer=F('integer').bitor(48))
|
||||||
|
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
|
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||||
|
@ -181,20 +181,6 @@ class ExpressionOperatorTests(TestCase):
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 27)
|
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 27)
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||||
|
|
||||||
def test_right_hand_bitwise_and(self):
|
|
||||||
# RH Bitwise ands on integers
|
|
||||||
Number.objects.filter(pk=self.n.pk).update(integer=15 & F('integer'))
|
|
||||||
|
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 10)
|
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
|
||||||
|
|
||||||
@skipUnlessDBFeature('supports_bitwise_or')
|
|
||||||
def test_right_hand_bitwise_or(self):
|
|
||||||
# RH Bitwise or on integers
|
|
||||||
Number.objects.filter(pk=self.n.pk).update(integer=15 | F('integer'))
|
|
||||||
|
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 47)
|
|
||||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
|
||||||
|
|
||||||
class FTimeDeltaTests(TestCase):
|
class FTimeDeltaTests(TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue