2010-01-08 3 views
7

Я хочу распечатать словарь, отсортированный по ключу. Сортировка ключей проста в представлении, просто поместив ключи в список и затем отсортировав список. Как я могу прокручивать ключи в шаблоне, а затем получать значение из словаря.Django | sort dict в шаблоне

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

(Просто сделал в пример ...) та часть, которая не работает является «company_dict.company.items» часть. Мне нужна «компания», чтобы быть ценной компанией. Прямо сейчас компания prat ищет ключ под названием «компания», а не стоимость «компании» из цикла выше.

Я делаю немного обработки, чтобы поместить словарь словарей вместе. Изменение компоновки данных на самом деле не является вариантом. Я считаю, что правильный подход заключается в том, чтобы написать шаблонный тег, просто хотел узнать, есть ли встроенный способ, который я пропустил.

+4

По какой причине вы не делаете это на виду? –

+0

Это куча обработки. И чтобы настроить его, чтобы не делать ничего в шаблоне, потребовался бы второй проход по данным. Наверное, я мог бы это сделать ... Поняв, можно ли оставить как есть, было бы лучше. – johannix

ответ

2

попробовать это: http://www.bhphp.com/blog4.php/2009/08/17/django-templates-and-dictionaries

пользовательских фильтров шаблон будет делать трюк.

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) 

больше на пользовательских фильтров шаблона: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#howto-custom-template-tags

в вашем примере вы могли бы сделать:

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

Спасибо большое! Мне пришлось изменить то, что вы сделали немного. Мой фильтр возвращает «значение [arg] .iteritems()», и шаблон выглядит так: {% для сотрудника, иждивенцы в company_dict | get_dict_and_iter: company%} – johannix

+0

эй все работает. большинство людей, использующих этот сайт, могут изменить то, что я сделал с их обстоятельствами. –

19

создать пользовательский фильтр, который так:

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 

то в шаблоне вы назовете его:

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

Вы можете получить отсортированный dict ключом.

+1

Возможно, почти точный дубликат, но пока другой этого не сделал, этот ответ помог мне и был гениальным дама, спасибо вам большое! – mVChr

+0

Это также помогло мне больше, чем предыдущий ответ! – Mibou

+0

* «Маркировка фильтра is_safe будет принудительно возвращать значение фильтра в строку. Если ваш фильтр должен возвращать логическое или другое нестроковое значение, то маркировка is_safe, вероятно, будет иметь непреднамеренные последствия (например, преобразование логического False в строку) False '). "* ([Django documentation] (https://docs.djangoproject.com/en/1.6/howto/custom-template-tags/#filters-and-auto-escaping)) Итак, это, вероятно, лучше для удаления этой строки is_safe. –

1

Это последнее решение было очень полезно для меня. Я использую Django 1.6.2, и, похоже, он преобразует dict в список с ключом как первый элемент этого списка, а контент - второй. Поэтому, даже когда я перехожу в диктофон, он рассматривает его как список. Так что я подправил выше, чтобы посмотреть, как это, и это работает для меня:

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

для некоторого reasone фильтр Turikumwe не работал для меня (python3.4, Django 1.7), так что я его переписать, чтобы вернуть список кортежей вместо SertedDict или 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 

Так что в шаблоне нам не нужно, чтобы получить .items

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

ответ Turikumwe получил меня близко, бу t не работает для моей среды: python3 и Django 1.10.

Я обнаружил, что применение фильтра с:

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

фактически приводит к ItemsView объекта, а не Dict. (Я подозреваю, что это проблема с python 2 против 3). С учетом ItemsView ответ еще проще

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 
Смежные вопросы