Loading django/template/smartif.py +6 −2 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ OPERATORS = { 'in': infix(9, lambda context, x, y: x.eval(context) in y.eval(context)), 'not in': infix(9, lambda context, x, y: x.eval(context) not in y.eval(context)), 'is': infix(10, lambda context, x, y: x.eval(context) is y.eval(context)), 'is not': infix(10, lambda context, x, y: x.eval(context) is not y.eval(context)), '==': infix(10, lambda context, x, y: x.eval(context) == y.eval(context)), '!=': infix(10, lambda context, x, y: x.eval(context) != y.eval(context)), '>': infix(10, lambda context, x, y: x.eval(context) > y.eval(context)), Loading Loading @@ -149,13 +150,16 @@ class IfParser(object): error_class = ValueError def __init__(self, tokens): # pre-pass necessary to turn 'not','in' into single token # Turn 'is','not' and 'not','in' into single tokens. l = len(tokens) mapped_tokens = [] i = 0 while i < l: token = tokens[i] if token == "not" and i + 1 < l and tokens[i + 1] == "in": if token == "is" and i + 1 < l and tokens[i + 1] == "not": token = "is not" i += 1 # skip 'not' elif token == "not" and i + 1 < l and tokens[i + 1] == "in": token = "not in" i += 1 # skip 'in' mapped_tokens.append(self.translate_token(token)) Loading docs/ref/templates/builtins.txt +14 −1 Original line number Diff line number Diff line Loading @@ -432,7 +432,8 @@ Use of actual parentheses in the :ttag:`if` tag is invalid syntax. If you need them to indicate precedence, you should use nested :ttag:`if` tags. :ttag:`if` tags may also use the operators ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``, ``in``, and ``is`` which work as follows: ``<=``, ``>=``, ``in``, ``not in``, ``is``, and ``is not`` which work as follows: ``==`` operator ^^^^^^^^^^^^^^^ Loading Loading @@ -526,6 +527,18 @@ Object identity. Tests if two values are the same object. Example:: This will output if and only if value is None. {% endif %} ``is not`` operator ^^^^^^^^^^^^^^^^^^^ .. versionadded:: 1.10 Tests if two values are not the same object. This is the negation of the ``is`` operator. Example:: {% if value is not None %} This will output if and only if value is not None. {% endif %} Filters ~~~~~~~ Loading docs/releases/1.10.txt +1 −1 Original line number Diff line number Diff line Loading @@ -409,7 +409,7 @@ Templates :class:`~django.template.backends.django.DjangoTemplates` backend and the :class:`~django.template.Engine` class. * Added the ``is`` comparison operator to the :ttag:`if` tag. * Added the ``is`` and ``is not`` comparison operators to the :ttag:`if` tag. * Allowed :tfilter:`dictsort` to order a list of lists by an element at a specified index. Loading tests/template_tests/syntax_tests/test_if.py +12 −0 Original line number Diff line number Diff line Loading @@ -537,3 +537,15 @@ class IfTagTests(SimpleTestCase): def test_if_is_no_match(self): output = self.engine.render_to_string('template', {'foo': 1}) self.assertEqual(output, 'no') @setup({'template': '{% if foo is not None %}yes{% else %}no{% endif %}'}) def test_if_is_not_match(self): # For this to act as a regression test, it's important not to use # foo=True because True is (not None) output = self.engine.render_to_string('template', {'foo': False}) self.assertEqual(output, 'yes') @setup({'template': '{% if foo is not None %}yes{% else %}no{% endif %}'}) def test_if_is_not_no_match(self): output = self.engine.render_to_string('template', {'foo': None}) self.assertEqual(output, 'no') Loading
django/template/smartif.py +6 −2 Original line number Diff line number Diff line Loading @@ -97,6 +97,7 @@ OPERATORS = { 'in': infix(9, lambda context, x, y: x.eval(context) in y.eval(context)), 'not in': infix(9, lambda context, x, y: x.eval(context) not in y.eval(context)), 'is': infix(10, lambda context, x, y: x.eval(context) is y.eval(context)), 'is not': infix(10, lambda context, x, y: x.eval(context) is not y.eval(context)), '==': infix(10, lambda context, x, y: x.eval(context) == y.eval(context)), '!=': infix(10, lambda context, x, y: x.eval(context) != y.eval(context)), '>': infix(10, lambda context, x, y: x.eval(context) > y.eval(context)), Loading Loading @@ -149,13 +150,16 @@ class IfParser(object): error_class = ValueError def __init__(self, tokens): # pre-pass necessary to turn 'not','in' into single token # Turn 'is','not' and 'not','in' into single tokens. l = len(tokens) mapped_tokens = [] i = 0 while i < l: token = tokens[i] if token == "not" and i + 1 < l and tokens[i + 1] == "in": if token == "is" and i + 1 < l and tokens[i + 1] == "not": token = "is not" i += 1 # skip 'not' elif token == "not" and i + 1 < l and tokens[i + 1] == "in": token = "not in" i += 1 # skip 'in' mapped_tokens.append(self.translate_token(token)) Loading
docs/ref/templates/builtins.txt +14 −1 Original line number Diff line number Diff line Loading @@ -432,7 +432,8 @@ Use of actual parentheses in the :ttag:`if` tag is invalid syntax. If you need them to indicate precedence, you should use nested :ttag:`if` tags. :ttag:`if` tags may also use the operators ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``, ``in``, and ``is`` which work as follows: ``<=``, ``>=``, ``in``, ``not in``, ``is``, and ``is not`` which work as follows: ``==`` operator ^^^^^^^^^^^^^^^ Loading Loading @@ -526,6 +527,18 @@ Object identity. Tests if two values are the same object. Example:: This will output if and only if value is None. {% endif %} ``is not`` operator ^^^^^^^^^^^^^^^^^^^ .. versionadded:: 1.10 Tests if two values are not the same object. This is the negation of the ``is`` operator. Example:: {% if value is not None %} This will output if and only if value is not None. {% endif %} Filters ~~~~~~~ Loading
docs/releases/1.10.txt +1 −1 Original line number Diff line number Diff line Loading @@ -409,7 +409,7 @@ Templates :class:`~django.template.backends.django.DjangoTemplates` backend and the :class:`~django.template.Engine` class. * Added the ``is`` comparison operator to the :ttag:`if` tag. * Added the ``is`` and ``is not`` comparison operators to the :ttag:`if` tag. * Allowed :tfilter:`dictsort` to order a list of lists by an element at a specified index. Loading
tests/template_tests/syntax_tests/test_if.py +12 −0 Original line number Diff line number Diff line Loading @@ -537,3 +537,15 @@ class IfTagTests(SimpleTestCase): def test_if_is_no_match(self): output = self.engine.render_to_string('template', {'foo': 1}) self.assertEqual(output, 'no') @setup({'template': '{% if foo is not None %}yes{% else %}no{% endif %}'}) def test_if_is_not_match(self): # For this to act as a regression test, it's important not to use # foo=True because True is (not None) output = self.engine.render_to_string('template', {'foo': False}) self.assertEqual(output, 'yes') @setup({'template': '{% if foo is not None %}yes{% else %}no{% endif %}'}) def test_if_is_not_no_match(self): output = self.engine.render_to_string('template', {'foo': None}) self.assertEqual(output, 'no')