Author: lukeplant Date: 2010-03-08 17:25:37 -0600 (Mon, 08 Mar 2010) New Revision: 12732
Modified: django/trunk/django/template/defaulttags.py django/trunk/django/template/smartif.py django/trunk/docs/ref/templates/builtins.txt django/trunk/docs/releases/1.2.txt django/trunk/tests/regressiontests/templates/smartif.py django/trunk/tests/regressiontests/templates/tests.py Log: Fixed #13058 - "smart if" template tag doesn't support "if not in ..." condition Thanks to ramusus for the report. Modified: django/trunk/django/template/defaulttags.py =================================================================== --- django/trunk/django/template/defaulttags.py 2010-03-08 20:53:51 UTC (rev 12731) +++ django/trunk/django/template/defaulttags.py 2010-03-08 23:25:37 UTC (rev 12732) @@ -806,8 +806,8 @@ Arguments and operators _must_ have a space between them, so ``{% if 1>2 %}`` is not a valid if tag. - All supported operators are: ``or``, ``and``, ``in``, ``==`` (or ``=``), - ``!=``, ``>``, ``>=``, ``<`` and ``<=``. + All supported operators are: ``or``, ``and``, ``in``, ``not in`` + ``==`` (or ``=``), ``!=``, ``>``, ``>=``, ``<`` and ``<=``. Operator precedence follows Python. """ Modified: django/trunk/django/template/smartif.py =================================================================== --- django/trunk/django/template/smartif.py 2010-03-08 20:53:51 UTC (rev 12731) +++ django/trunk/django/template/smartif.py 2010-03-08 23:25:37 UTC (rev 12732) @@ -97,6 +97,7 @@ 'and': infix(7, lambda x, y: x and y), 'not': prefix(8, operator.not_), 'in': infix(9, lambda x, y: x in y), + 'not in': infix(9, lambda x, y: x not in y), '=': infix(10, operator.eq), '==': infix(10, operator.eq), '!=': infix(10, operator.ne), @@ -150,11 +151,23 @@ error_class = ValueError def __init__(self, tokens): - self.tokens = map(self.translate_tokens, tokens) + # pre-pass necessary to turn 'not','in' into single token + 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": + token = "not in" + i += 1 # skip 'in' + mapped_tokens.append(self.translate_token(token)) + i += 1 + + self.tokens = mapped_tokens self.pos = 0 self.current_token = self.next() - def translate_tokens(self, token): + def translate_token(self, token): try: op = OPERATORS[token] except (KeyError, TypeError): Modified: django/trunk/docs/ref/templates/builtins.txt =================================================================== --- django/trunk/docs/ref/templates/builtins.txt 2010-03-08 20:53:51 UTC (rev 12731) +++ django/trunk/docs/ref/templates/builtins.txt 2010-03-08 23:25:37 UTC (rev 12732) @@ -440,7 +440,12 @@ instance that belongs to the QuerySet. {% endif %} +``not in`` operator +~~~~~~~~~~~~~~~~~~~~ +Not contained within. This is the negation of the ``in`` operator. + + The comparison operators cannot be 'chained' like in Python or in mathematical notation. For example, instead of using:: Modified: django/trunk/docs/releases/1.2.txt =================================================================== --- django/trunk/docs/releases/1.2.txt 2010-03-08 20:53:51 UTC (rev 12731) +++ django/trunk/docs/releases/1.2.txt 2010-03-08 23:25:37 UTC (rev 12732) @@ -636,9 +636,9 @@ There's really no reason to use ``{% ifequal %}`` or ``{% ifnotequal %}`` anymore, unless you're the nostalgic type. -The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=`` and -``in``, all of which work like the Python operators, in addition to ``and``, -``or`` and ``not``, which were already supported. +The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=``, +``in`` and ``not in``, all of which work like the Python operators, in addition + to ``and``, ``or`` and ``not``, which were already supported. Also, filters may now be used in the ``if`` expression. For example: Modified: django/trunk/tests/regressiontests/templates/smartif.py =================================================================== --- django/trunk/tests/regressiontests/templates/smartif.py 2010-03-08 20:53:51 UTC (rev 12731) +++ django/trunk/tests/regressiontests/templates/smartif.py 2010-03-08 23:25:37 UTC (rev 12732) @@ -27,6 +27,13 @@ self.assertCalcEqual(False, [1, 'in', None]) self.assertCalcEqual(False, [None, 'in', list_]) + def test_not_in(self): + list_ = [1,2,3] + self.assertCalcEqual(False, [1, 'not', 'in', list_]) + self.assertCalcEqual(True, [4, 'not', 'in', list_]) + self.assertCalcEqual(False, [1, 'not', 'in', None]) + self.assertCalcEqual(True, [None, 'not', 'in', list_]) + def test_precedence(self): # (False and False) or True == True <- we want this one, like Python # False and (False or True) == False Modified: django/trunk/tests/regressiontests/templates/tests.py =================================================================== --- django/trunk/tests/regressiontests/templates/tests.py 2010-03-08 20:53:51 UTC (rev 12731) +++ django/trunk/tests/regressiontests/templates/tests.py 2010-03-08 23:25:37 UTC (rev 12732) @@ -611,6 +611,12 @@ 'if-tag-lte-01': ("{% if 1 <= 1 %}yes{% else %}no{% endif %}", {}, "yes"), 'if-tag-lte-02': ("{% if 2 <= 1 %}yes{% else %}no{% endif %}", {}, "no"), + # Contains + 'if-tag-in-01': ("{% if 1 in x %}yes{% else %}no{% endif %}", {'x':[1]}, "yes"), + 'if-tag-in-02': ("{% if 2 in x %}yes{% else %}no{% endif %}", {'x':[1]}, "no"), + 'if-tag-not-in-01': ("{% if 1 not in x %}yes{% else %}no{% endif %}", {'x':[1]}, "no"), + 'if-tag-not-in-02': ("{% if 2 not in x %}yes{% else %}no{% endif %}", {'x':[1]}, "yes"), + # AND 'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'), 'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'), -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.