【发布时间】:2011-05-08 06:55:26
【问题描述】:
我有一个类似的查询集:
items = Item.objects.all()
项目有一个“名称”字段。在我要展示的模板中:
- 一个
- 轴
- 酒精
- B
- 火箭筒
- C
- 硬币
- 墨盒
- S
- 剑
- 麻雀
因此项目按第一个字母排序和分组。缺少的字母被省略。有人有什么想法吗?
【问题讨论】:
标签: django sorting django-templates
我有一个类似的查询集:
items = Item.objects.all()
项目有一个“名称”字段。在我要展示的模板中:
因此项目按第一个字母排序和分组。缺少的字母被省略。有人有什么想法吗?
【问题讨论】:
标签: django sorting django-templates
如果您只关心它在页面上的显示,那么有一个模板标签。首先,在课堂上定义一个组织原则。在您的情况下,它是第一个字母:
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>
【讨论】:
{% regroup items by name|first|upper as letter_list %}
只是想补充一点,如果你使用它并且你的项目有一个小写的第一个字符,它将是一个单独的组。我在上面加上了。
return self.name and self.name.upper()[0] or ''
【讨论】:
或者,您可以在模板中使用 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>
【讨论】:
更容易。您可以在“重新组合”中按第一个字母进行分组:
{% 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 中测试
【讨论】:
对于 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"
],
......
}
【讨论】:
这是直接用 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 这只是概念证明。
无论您做什么,都不在循环中添加查询调用。
【讨论】:
itertools._grouper object 是另一个可迭代对象,注意循环有 alphabet_letter 和 items。 items 将是一个生成器,如果您需要多次访问它,您需要这样做:items = list(items) 在循环内。如果这些都没有帮助,请添加一个新问题并将其链接到此处,我会解决您的独特问题。