Search code examples
pythondjangojinja2enumerate

How to use enumerate(zip(seq1,seq2)) in jinja2?


I'm trying to color some sequences of RNA using Django. I'm using enumerate and zip to find equals index in list. for example:

for i, (a, b) in enumerate(zip(seq1, seq2)):
        if a == b and i not in green:
            <p style="color: green;">{{i}}</p>

        elif a != b and i not in red:
            <p style="color: red;">{{i}}</p>

I recive this error in my template:

'for' statements should use the format 'for x in y': for i, (a, b) in enumerate(zip(seq1, seq2)):


Solution

  • I think the Jinja template engine has problems parsing the i, (a, b) part in the for loop here, so perhaps it is worth submitting a ticket for this. Perhaps it is intended behavior.

    Anyway, you can zip with a 3-tuple here. As first iterable to zip, we can take itertools.count [python-doc]. You thus pass a reference 'count' with the itertools.count() to the context, and then you render with:

    {% for i, a, b in zip(indices(), seq1, seq2) %}
         {# ... #}
    {% endfor %}

    For example:

    >>> from jinja2 import Template
    >>> from itertools import count
    >>> Template('{% for i, a, b in zip(indices(), seq1, seq2) %} {{ (i, a, b) }}{% endfor %}').render(indices=count, seq1='foobar', seq2='babbaa', zip=zip)
    " (0, 'f', 'b') (1, 'o', 'a') (2, 'o', 'b') (3, 'b', 'b') (4, 'a', 'a') (5, 'r', 'a')"
    

    That being said, I strongly advise not to write business logic in the templates. In fact this is the main reason why Django template engines do not allow such syntax in the first place. It is probably much better to create the zip object in the view, and pass it through the context to the render engine.