Django按首字母分组查询集?

时间:2010-11-11 05:35:14

标签: django sorting django-templates

我有一个QuerySet,如:

items = Item.objects.all()

项目有一个'名称'字段。在我想要显示的模板中:

  • A
  • 火箭筒
  • C
  • 硬币
  • 墨盒
  • 取值
  • 麻雀

所以这些物品是按照第一个字母排序和分组的。遗漏的字母被省略。有没有人有任何想法?

6 个答案:

答案 0 :(得分:19)

如果您关心的是它在页面上的显示,那么就有一个模板标签。首先,在课堂上定义组织原则。在你的情况下,这是第一个字母:

class Item(models.Model):
    ...

    def first_letter(self):
        return self.name and self.name[0] or ''

然后使用first_letter调用在模板中定义重组:

{% regroup items by first_letter as letter_list %}
<ul> 
{% for letter in letter_list %}
  <li>{{ letter.grouper }}
    <ul>
        {% for item in letter.list %}
        <li>{{ item.name }}</li>
        {% endfor %}
    </ul>
  </li>
{% endfor %}
</ul>

答案 1 :(得分:6)

只是想补充一点,如果您使用此项并且您的项目具有小写的第一个字符,那么它将是一个单独的组。我加了鞋面。

return self.name and self.name.upper()[0] or ''

答案 2 :(得分:5)

或者,您可以在模板中使用slice内联,而无需在模型上使用first_letter方法。

{% regroup items by name|slice:":1" as letter_list %}
<ul> 
{% for letter in letter_list %}
  <li>{{ letter.grouper }}
    <ul>
        {% for item in letter.list %}
        <li>{{ item.name }}</li>
        {% endfor %}
    </ul>
  </li>
{% endfor %}
</ul>

答案 3 :(得分:0)

更容易。您可以在'重新组合'中首先进行分组:

{% regroup items|dictsort:"name" by name.0 as item_letter %}
<ul>
{% for letter in item_letter %}
    <h4>{{ letter.grouper|title }}</h4>
    {% for i in letter.list|dictsort:"name" %}
        <li>{{ i.name }}</li>
    {% endfor %}
{% empty %}
    <span>There is no items yet...</span>
{% endfor %}
</ul>
在这种情况下,

name.0与Python中的item.name[0]相同。

在Django 1.10中测试

答案 4 :(得分:0)

对于Django REST,你可以这样做,

import string
import collections

from rest_framework.response import Response
from rest_framework import status, viewsets

def groupby(self, request):
    result = []
    for i in list(string.ascii_uppercase):
        c = City.objects.filter(name__startswith=i)
        if c:
            result.append((i, map((lambda x: x['name']),list(c.values('name')))
            ))
    return Response(collections.OrderedDict(sorted(dict(result).items())), status=status.HTTP_200_OK)

城市模型

class City(models.Model):
    """All features model"""

    name = models.CharField(max_length=99)

响应

{
    "A": [
        "Adelanto",
        "Azusa",
        "Alameda",
        "Albany",
        "Alhambra",
        "Anaheim"
    ],
    "B": [
        "Belmont",
        "Berkeley",
        "Beverly Hills",
        "Big Sur",
        "Burbank"
    ],
    ......

}

答案 5 :(得分:0)

这是直接使用Django和Python的另一种做法。提供的另一种解决方案效率很低

import itertools

collector = {}
item_qs = Item.objects.all().order_by('name')
for alphabet_letter, items in itertools.groupby(item_qs, lambda x: x.name[0].lower()):
    # you can do any modifications you need at this point
    # you can do another loop if you want or a dictionary comprehension
    collector[alphabet_letter] = items  

这给你什么?一次查询数据库。

我应该使用collector吗?不,您可能应该使用yield,这只是概念的证明。

无论您做什么,都不要不要在循环内添加查询调用。