【问题标题】:Django | sort dict in template姜戈 |在模板中排序字典
【发布时间】:2010-01-08 00:13:50
【问题描述】:

我想打印一个字典,按键排序。在视图中对键进行排序很容易,只需将键放在列表中,然后对列表进行排序。如何遍历模板中的键,然后从字典中获取值。

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

(只是编了个例子……) 不起作用的部分是“company_dict.company.items”部分。我需要“公司”成为公司的价值。现在公司 prat 正在从上面的循环中寻找一个名为“company”的键,而不是“company”的值。

我正在做一些处理来将字典放在一起。更改数据的布局并不是一个真正的选择。我认为正确的方法是写一个模板标签,只是想知道是否有我错过的内置方式。

【问题讨论】:

  • 您为什么不在视图中执行此操作?
  • 是一堆处理。并将其设置为不必在模板中执行任何操作,需要对数据进行第二次传递。我想我可以这样做......我想如果可以就这样离开会更好。
  • Django 的内置过滤器dictsort 根据键对值进行排序,但它本身不对键进行排序。

标签: python django


【解决方案1】:

创建一个自定义过滤器,如下所示:

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 %}

您将能够通过Key获取排序的dict。

【讨论】:

  • 可能几乎完全相同,但另一个没有,这个答案对我有帮助,而且非常棒,非常感谢!
  • 它对我的帮助也超过了之前的答案!
  • "将过滤器标记为 is_safe 会将过滤器的返回值强制转换为字符串。如果您的过滤器应返回布尔值或其他非字符串值,则将其标记为 is_safe 可能会产生意想不到的后果(例如就像将布尔值 False 转换为字符串 'False')。" (django documentation) 所以,最好删除 is_safe 行。
  • 久经考验。完美运行!感谢您的解决方案。
【解决方案2】:

自定义模板过滤器可以解决问题。

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 %}

【讨论】:

  • 非常感谢!我不得不修改你所做的一点。我的过滤器返回“value[arg].iteritems()”,模板如下所示:{% for employee,dependents in company_dict|get_dict_and_iter:company %}
  • 嘿,不管用什么。大多数使用这个网站的人也可以修改我对他们的情况所做的事情。
【解决方案3】:

最后一个解决方案对我也非常有用。我正在使用 Django 1.6.2,它似乎正在将一个字典转换为一个列表,其中键作为该列表的第一个元素,内容作为第二个元素。因此,即使我传入一个字典,它也会将其视为一个列表。所以我调整了上面的样子,它对我有用:

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

【讨论】:

    【解决方案4】:

    由于某种原因,Turikumwe 的过滤器对我不起作用(python3.4,Django 1.7),所以我将其重写为返回元组列表而不是 SertedDictOrderedDict

    @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 %}
    

    【讨论】:

      【解决方案5】:

      Turikumwe 的回答让我很接近,但不适用于我的环境:python3 和 Django 1.10。

      我发现使用以下方法调用过滤器:

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

      实际上会产生一个 ItemsView 对象,而不是一个字典。 (我怀疑这是 python 2 vs 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
      

      【讨论】:

        【解决方案6】:

        你可以使用django的dictsort或者dictsortreversed

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

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

        【讨论】:

          猜你喜欢
          • 2014-05-18
          • 2020-08-17
          • 2011-05-13
          • 2021-08-11
          • 1970-01-01
          • 2012-10-25
          • 1970-01-01
          • 2016-08-13
          • 1970-01-01
          相关资源
          最近更新 更多