2010-01-14 6 views
25

Mi código de la vista se ve básicamente como esto:¿Accediendo a un dict por variable en las plantillas de Django?

context = Context() 
context['my_dict'] = {'a': 4, 'b': 8, 'c': 15, 'd': 16, 'e': 23, 'f': 42 } 
context['my_list'] = ['d', 'f', 'e', 'b', 'c', 'a'] 

Y lo que me gustaría hacer en mi plantilla de Django es la siguiente:

<ul> 
{% for item in my_list %} 
    <li>{{ item }} : {{ my_dict.item }}</li> 
{% endfor %} 
</ul> 

Y me gustaría esto a la salida:

<ul> 
    <li> d : 16 </li> 
    <li> f : 42 </li> 
    <li> e : 23 </li> 
    <li> b : 8 </li> 
    <li> c : 15 </li> 
    <li> a : 4 </li> 
</ul> 

Pero la referencia al dict por nombre de variable a través de {{ my_dict.item }} en realidad no funciona. Sospecho que internamente está haciendo my_dict['item'] en lugar de my_dict[item]. ¿Hay alguna forma de evitar esto?

+0

Por supuesto, siempre podía añadir más código en la vista que decir: contexto [ 'my_derefernced'] = [(v, el contexto [my_dict] [v]) para v en context ['my_list']], pero prefiero no tener que hacer eso. Los dicts pueden ser bastante grandes. – slacy

+0

Mire esta gran solución: http://stackoverflow.com/questions/35948/django-templates-and-variable-attributes – fiatjaf

+0

Si los dicts son grandes, ¿por qué no usar generadores? Tal vez algo como esto: 'context ['my_dereferenced'] = ((v, context [my_dict] [v]) para v en el contexto ['mi_lista'])' – user193130

Respuesta

15

No hay forma de orden interna para hacer eso, lo que se necesita para escribir un filtro de plantilla simple de hacer esto: http://code.djangoproject.com/ticket/3371

+0

Gracias Alex. Sabía que podía escribir un filtro de plantilla. ¿Por qué no modificar el procesador de plantilla para incluir pasos para {{foo.bar}} para probar foo.resolve_variable (bar, context) y foo [resolve_variable (bar, context)]? – slacy

+5

Claro que parece una tontería tener que escribir {{my_dict | access: item}} – slacy

+2

@slacy Si eso te parece antinatural e inmanejable, podrías considerar visitar a Jinja. Es un poco más Pythonic y mucho menos obstinado que el sistema de creación de plantillas de Django. No todos están de acuerdo, pero personalmente me gusta más. –

5

Aquí es un caso de uso de la respuesta sugerida.

En este ejemplo, creé una plantilla genérica para generar datos tabulares de una vista. Los metadatos sobre las columnas se mantienen en contexto ["columnaMeta"].

Dado que este es un diccionario, no puedo confiar en las claves para dar salida a las columnas en orden, así que tengo las claves en una lista separada para esto.

En mi view.py:


c["columns"] = ["full_name","age"] 
c["columnMeta"] = {"age":{},"full_name":{"label":"name"}} 

En mi archivo templatetags:


@register.filter 
def getitem (item, string): 
    return item.get(string,'') 

En mi plantilla:

 
<tr> 
<!-- iterate columns in order specified --> 
{% for key in columns %} 
<th> 
<span class="column-title"> 
    <!-- look label in meta dict. If not found, use the column key --> 
    {{columnMeta|getitem:key|getitem:"label"|default:key}} 
    </span> 
</th> 
{% endfor %}</tr> 
2

Para mis necesidades, quería un único filtro de plantilla que trabajaría para dicts, listas y tuplas. Por lo tanto, esto es lo que utilizo:

@register.filter 
def get_item(container, key): 
    if type(container) is dict: 
     return container.get(key) 
    elif type(container) in (list, tuple): 
     return container[key] if len(container) > key else None 
    return None 
Cuestiones relacionadas