2010-01-08 27 views
7

Quiero imprimir un diccionario, ordenado por la clave. Clasificar las teclas es fácil en la vista, simplemente colocando las teclas en una lista y luego ordenando la lista. ¿Cómo puedo recorrer las claves en la plantilla y luego obtener el valor del diccionario?Django | ordenar dict en la plantilla

{% for company in companies %} 
    {% for employee, dependents in company_dict.company.items %} 
    {% endfor %} 
{% endfor %} 

(acaba de hacer el ejemplo ...) La parte que no funciona es la parte "company_dict.company.items". Necesito que la "compañía" sea el valor de la compañía. En este momento, el prat de la compañía está buscando una clave llamada "compañía", no el valor de "compañía" del ciclo anterior.

Estoy haciendo un poco de procesamiento para unir el diccionario de diccionarios. Cambiar el diseño de los datos no es realmente una opción. Me imagino que el enfoque correcto es escribir una etiqueta de plantilla, solo quería saber si había una forma incorporada en la que me perdí.

+4

¿Por qué razón no haces esto en la vista? –

+0

Es un montón de procesamiento. Y para configurarlo para no tener que hacer nada en la plantilla, daría una segunda pasada a los datos. Supongo que podría hacer eso ... Me imaginé que si fuera posible irse como está, sería mejor. – johannix

Respuesta

2

probar esto: http://www.bhphp.com/blog4.php/2009/08/17/django-templates-and-dictionaries filtro de plantilla

una costumbre hará el truco.

from django import template 
register = template.Library() 

def dict_get(value, arg): 
    #custom template tag used like so: 
    #{{dictionary|dict_get:var}} 
    #where dictionary is duh a dictionary and var is a variable representing 
    #one of it's keys 

    return value[arg] 

register.filter('dict_get',dict_get) 

más en filtros Plantilla de encargo: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#howto-custom-template-tags

en su ejemplo que haría:

{% for employee, dependents in company_dict|company %} 
+2

¡Muchas gracias! Tuve que modificar lo que hiciste un poco. Mi filtro devuelve "value [arg] .iteritems()" y la plantilla se ve así: {% para empleado, dependientes en company_dict | get_dict_and_iter: company%} – johannix

+0

hey lo que sea que funcione. la mayoría de las personas que usan este sitio podrían modificar lo que hice con sus circunstancias también. –

19

crear un filtro personalizado, que es la siguiente:

from django import template 
from django.utils.datastructures import SortedDict 

register = template.Library() 

@register.filter(name='sort') 
def listsort(value): 
    if isinstance(value, dict): 
     new_dict = SortedDict() 
     key_list = sorted(value.keys()) 
     for key in key_list: 
      new_dict[key] = value[key] 
     return new_dict 
    elif isinstance(value, list): 
     return sorted(value) 
    else: 
     return value 
    listsort.is_safe = True 

luego en su plantilla deberá llamarlo usando:

{% for key, value in companies.items|sort %} 
     {{ key }} {{ value }} 
{% endfor %} 

Podrá obtener el dictado ordenado por clave.

+1

Tal vez duplicado casi exacto, pero mientras que el otro no, esta respuesta me ayudó y es papá-chicle brillante, ¡muchas gracias! – mVChr

+0

¡También me ayudó más que la respuesta anterior! – Mibou

+0

* "Marcar un filtro is_safe forzará el valor de retorno del filtro a una cadena. Si su filtro debe devolver un valor booleano u otro que no sea cadena, marcarlo is_safe probablemente tendrá consecuencias involuntarias (como convertir un booleano falso en la cadena ' False '). "* ([Documentación de django] (https://docs.djangoproject.com/en/1.6/howto/custom-template-tags/#filters-and-auto-escaping)) Por lo tanto, es probablemente mejor para eliminar esa línea is_safe. –

1

Esta última solución fue muy útil para mí también. Estoy usando Django 1.6.2, y parece ser convertir un dict a una lista con la clave como primer elemento de esa lista y el contenido como el segundo. Entonces, incluso cuando paso en un dict, lo trata como una lista. Así que Ajustado el anterior a este aspecto, y funciona para mí:

@register.filter(name='sort') 
def listsort(value): 
    if isinstance(value, list): 
     return sorted(value, key=lambda k:k[0]) 
    else: 
     return value 
0

por alguna reasone filtro de Turikumwe no funcionó para mí (python3.4, Django 1.7), por lo que vuelvo a escribir a una lista de tuplas volver en lugar de SertedDict o OrderedDict:

@register.filter(name='sort') 
def listsort(value): 
    if isinstance(value, dict): 
     a = [] 
     key_list = sorted(value.keys()) 
     for key in key_list: 
      a.append((key, value[key])) 
     return a 
    elif isinstance(value, list): 
     return sorted(value) 
    else: 
     return value 

listsort.is_safe = True 

Así que en la plantilla que no es necesario para obtener .items

{% for key, value in companies|sort %} 
     {{ key }} {{ value }} 
{% endfor %} 
0

respuesta de Turikumwe me hizo estrecha, bu No funcionó para mi entorno: python3 y Django 1.10.

He encontrado que la invocación del filtro con:

{% for key, value in companies.items|sort %} 
     {{ key }} {{ value }} 
{% endfor %} 

realidad se traduce en un objeto ItemsView, no un dict. (Sospecho que esto es un problema python 2 vs 3). Dado el ItemsView, la respuesta es aún más fácil

from django import template 
from django.utils.datastructures import ItemsView 

register = template.Library() 

@register.filter(name='sort') 
def listsort(value): 
    if isinstance(value, ItemsView) or isinstance(value, list): 
     return sorted(value) 
    else: 
     return value 
Cuestiones relacionadas