widgets fields python django django-templates

python - fields - Iteración a través de dos listas en plantillas de Django



django forms widgets (6)

Aquí está el templatetag {% for%} modificado que permite iterar varias listas a la vez einculinándolas antes:

import re from itertools import izip from django import template from django.template.base import TemplateSyntaxError from django.template.defaulttags import ForNode register = template.Library() class ZipExpression(object): def __init__(self, var): self.var = var def resolve(self, *args, **kwargs): return izip(*( f.resolve(*args, **kwargs) for f in self.var )) @register.tag(''for'') def do_for(parser, token): """ For tag with ziping multiple iterables. """ bits = token.contents.split() if len(bits) < 4: raise TemplateSyntaxError("''foreach'' statements should have at least" " four words: %s" % token.contents) is_reversed = False try: in_index = bits.index(''in'') sequence = bits[in_index+1:] if sequence[-1] == ''reversed'': is_reversed = True sequence.pop() if not sequence or ''in'' in sequence: raise ValueError sequence = re.split(r'' *, *'', '' ''.join(sequence)) except ValueError: raise TemplateSyntaxError( "''foreach'' statements should use the format" " ''foreach a,b,(...) in x,y,(...)'': %s" % token.contents) loopvars = re.split(r'' *, *'', '' ''.join(bits[1:in_index])) for var in loopvars: if not var or '' '' in var: raise TemplateSyntaxError("''foreach'' tag received an invalid" " argumewnt: %s" % token.contents) if len(sequence) > 1: sequence = ZipExpression(map(parser.compile_filter, sequence)) else: sequence = parser.compile_filter(sequence[0]) nodelist_loop = parser.parse((''empty'', ''endfor'',)) token = parser.next_token() if token.contents == ''empty'': nodelist_empty = parser.parse((''endfor'',)) parser.delete_first_token() else: nodelist_empty = None return ForNode( loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty)

Simplemente guárdelo como una biblioteca de plantillas e impórtelo en su plantilla. Anulará la etiqueta incorporada {% for%} (no se preocupe, es compatible con versiones anteriores).

Ejemplo de uso:

{% for a,b in foo, moo %} {{ a }} {{ b }} {% endfor %}

Quiero hacer la iteración de la lista a continuación en las plantillas de django:

foo = [''foo'', ''bar'']; moo = [''moo'', ''loo'']; for (a, b) in zip(foo, moo): print a, b

código django:

{%for a, b in zip(foo, moo)%} {{a}} {{b}} {%endfor%}

Aparece el siguiente error cuando pruebo esto:

File "/base/python_lib/versions/third_party/django-0.96/django/template/defaulttags.py", line 538, in do_for raise TemplateSyntaxError, "''for'' statements should have either four or five words: %s" % token.contents

¿Cómo logro esto?


Es posible hacer

{% for ab in mylist %} {{ab.0}} {{ab.1}} {% endfor %}

pero no puede hacer una llamada para zip dentro de la estructura for . Primero tendrá que almacenar la lista comprimida en otra variable y luego iterar sobre ella.


Puede hacer que las propiedades de objetos foo de los objetos moo en el lado del servidor.

for f, b in zip(foo, bar): f.foosBar = b context = { "foo": foo }

Esto es especialmente limpio cuando la segunda lista son propiedades de la primera (que generalmente es el caso).

users = User.objects.all() for user in users: user.bestFriend = findBestFriendForUser(user) context = { "users": users }


Puedes usar zip en tu vista:

mylist = zip(list1, list2) return render_to_response(''template.html'', {''list'': list, ... })

y en el uso de tu plantilla

{% for item1, item2 in mylist %}

para iterar a través de ambas listas.

Esto debería funcionar con todas las versiones de Django.


Simplemente defina zip como un filtro de plantilla :

@register.filter(name=''zip'') def zip_lists(a, b): return zip(a, b)

Luego, en tu plantilla:

{%for a, b in first_list|zip:second_list %} {{a}} {{b}} {%endfor%}


django-multiforloop para resolver este problema. Del LÉAME:

Con django-multiforloop instalado, renderizando esta plantilla

{% for x in x_list; y in y_list %} {{ x }}:{{ y }} {% endfor %}

con este contexto

context = { "x_list": (''one'', 1, ''carrot''), "y_list": (''two'', 2, ''orange'') }

saldrá

one:two 1:2 carrot:orange