开发者

Django | sort dict in template

开发者 https://www.devze.com 2022-12-15 15:44 出处:网络
I want to print out a dictionary, sorted by the key. Sorting the keys is easy in the view, b开发者_C百科y just putting the keys in a list and then sorting the list. How can I loop through the keys in

I want to print out a dictionary, sorted by the key. Sorting the keys is easy in the view, b开发者_C百科y just putting the keys in a list and then sorting the list. How can I loop through the keys in the template and then get the value from the dictionary.

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

(Just made up the example...) The part that doesn't work is the "company_dict.company.items" part. I need the "company" to be the value of company. Right now the company prat is looking for a key named "company" not the value of "company" from the loop above.

I'm doing a bit of processing to put the dictionary of dictionaries together. Changing the layout of the data isn't really an option. I figure the right approach is to write up a template tag, just wanted to know if there was a built-in way I missed.


create a custom filter, which is like this:

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

then in your template you shall call it using:

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

You will be able to get the sorted dict by Key.


a custom template filter will do the trick.

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)

more on custom template filters: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#howto-custom-template-tags

in your example you'd do:

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


This last solution was very useful to me too. I'm using Django 1.6.2, and it seems to be converting a dict to a list with the key as the first elemement of that list and the content as the second. So even when I pass in a dict, it treats it as a list. So I tweaked the above to look like this, and it works for me:

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


for some reasone Turikumwe's filter not worked for me (python3.4, Django 1.7), so I rewrite it to return list of tuples instead of SertedDict or 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

So in template we don't need to get .items

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


Turikumwe's answer got me close, but did not work for my environment: python3 and Django 1.10.

I found that invoking the filter with:

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

actually results in a ItemsView object, not a dict. (I suspect this is a python 2 vs 3 issue). Given the ItemsView, the answer is even easier

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


You can use django's dictsort or dictsortreversed.

{% for user in list_users|dictsort:'created_at' %}
    {{user.username}} - {{user.created_at}}
{% endfor %}

or

{% for user in list_users|dictsortreversed:'created_at' %}
    {{user.username}} - {{user.created_at}}
{% endfor %}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号