Commit 960af902 authored by Luke Plant's avatar Luke Plant
Browse files

Fixed #13058 - "smart if" template tag doesn't support "if not in ..."...

Fixed #13058 - "smart if" template tag doesn't support "if not in ..." condition                                                                                                                         

Thanks to ramusus for the report.



git-svn-id: http://code.djangoproject.com/svn/django/trunk@12732 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 021ba30a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -806,8 +806,8 @@ def do_if(parser, token):
    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.
    """
+15 −2
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ OPERATORS = {
    '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 @@ class IfParser(object):
    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):
+5 −0
Original line number Diff line number Diff line
@@ -440,6 +440,11 @@ how ``x in y`` will be interpreted::
      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::
+3 −3
Original line number Diff line number Diff line
@@ -636,9 +636,9 @@ You can now do this:
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:

+7 −0
Original line number Diff line number Diff line
@@ -27,6 +27,13 @@ class SmartIfTests(unittest.TestCase):
        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
Loading