【问题标题】:How to sort a list of objects in a template in alphabetic order?如何按字母顺序对模板中的对象列表进行排序?
【发布时间】:2014-02-26 00:06:36
【问题描述】:

我想在 Django 通用显示视图 ListView 类中显示对象列表。而且,为了让它更漂亮,我尝试按字母顺序对其进行排序。所以,我使用内置的dictsort标签对列表进行排序。

这是我使用的代码的摘要:

{% for item in object_list|dictsort:"name" %}
  ...
{% empty %}
  ...
{% endfor %}

问题在于它根据字符的 ASCII 值对名称进行排序,这意味着 bigcaps 和 smallcaps 的排序方式不同。这是一个例子:

Bob
Eve
alice
zoe

而且,我想要的是以下内容:

alice
Bob
Eve
zoe

我查看了 SO 中的文档和几个问题,但没有成功。所以,如果有人有办法实现这一点,我将非常感激。

【问题讨论】:

    标签: django django-templates django-template-filters


    【解决方案1】:

    一个非常老的问题,但这个问题刚刚出现在我身上。只需将.lower 添加到dictsort,例如:

    {% for item in object_list|dictsort:"name.lower" %}

    【讨论】:

      【解决方案2】:

      我知道这是一个老问题,但我看到的对列表不区分大小写进行排序的最简单方法是:

      name_of_list.sort(key=str.lower)

      参考链接: https://www.afternerd.com/blog/python-sort-list/

      您可以使用以下代码对其进行测试:

      my_list = ["alice", "Bob", "eve", "Zoe"]
      my_list.sort()
      print("case sensitive list:")
      print(my_list)
      
      my_list.sort(key=str.lower)
      print("case insensitive list:")
      print(my_list)
      

      然后,当您在模板中显示列表时,项目将已经排序。

      【讨论】:

        【解决方案3】:

        其实我在.../lib/python2.7/site-packagesdjango/template/defaultfilters.py中查看了dictsort的原始代码。而且,我刚刚添加了一个自定义的cmp 方法:

        @register.filter
        def sort_lower(value, arg):
            try:
                return sorted(value, key=Variable(arg).resolve,
                              cmp=lambda x,y: cmp(x.lower(), y.lower()))
            except (TypeError, VariableDoesNotExist):
                return ''
        

        这种方式允许按我的情况所需的子字段(例如 field1.field2)进行排序。

        【讨论】:

          【解决方案4】:

          您需要编写一个按小写排序的自定义过滤器。很简单:

          @register.filter
          def sort_lower(lst, key_name):
              return sorted(lst, key=lambda item: getattr(item, key_name).lower())
          

          但是,如果您的列表是数据库中的一组对象,那么您实际上不应该在 Python 中对它们进行排序 - 您应该让数据库按照您想要的顺序返回它们。

          编辑

          您如何使用过滤器?应该和dictsort一模一样:object_list|sort_lower:"name"

          要对数据库中的查询集进行排序,可以使用extra 方法添加小写版本的字段:

          MyModel.objects.all().extra(select={'lower_name': 'LOWER(NAME)'}, order_by='lower_name')
          

          【讨论】:

          • 首先,我试图定义我自己的过滤器,正如你提到的那样,但我没有设法让它在模板中工作。我在for 循环中传递参数时遇到问题。其次,如何让数据库从模板中返回排序后的列表?
          • 我得到一个'MyClass' object has no attribute '__getitem__' 错误,我试着看看为什么。但是,我有点卡住了。
          • 对不起,我已经更新了代码。但正如我所说,您应该使用查询版本。
          • 我设法让第一个方法以与dictsort 类似的方式工作。但是,我不明白为什么在数据库中添加一个额外的字段比在请求之后对其进行排序更好。
          • 这听起来很...英语。 L10N开启时会怎样?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-02
          • 2014-02-08
          • 2013-10-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多