Django ListView模板按分类拆分列表:是否有简便实现方式?
不用复杂过滤器/标签,两种简便实现方式
嘿,你的需求其实完全不用折腾自定义过滤器或者标签,有两个超直接的简便方法,选一个适合你的就行:
方法一:模板内直接判断(无需修改太多后端)
既然你已经把数据按分类排好序了,那在模板里只需要跟踪上一个项的分类,每次遇到新分类就输出标题就行。Django模板里用{% with %}就能轻松实现“临时变量”的效果:
后端(只需确保queryset已排序)
class YourListView(ListView): model = YourModel template_name = "your_template.html" def get_queryset(self): # 先按category排序,这是前提! return super().get_queryset().order_by("category", "name")
模板代码
{% for item in object_list %} <!-- 第一次循环,或者当前项分类和上一个不一样时,输出分类标题 --> {% if forloop.first or item.category != previous_category %} <h2>{{ item.category.name }}</h2> {% endif %} <!-- 输出当前列表项 --> <div class="list-item">{{ item.title }}</div> <!-- 更新“上一个分类”变量,供下一次循环对比 --> {% with previous_category=item.category %} {% endwith %} {% endfor %}
方法二:后端提前分组(模板更简洁)
如果觉得模板里写判断有点乱,也可以在ListView的get_context_data里用Python的itertools.groupby提前把数据按分类分组,模板直接循环分组后的结果就行:
后端代码
from itertools import groupby from django.views.generic import ListView class YourListView(ListView): model = YourModel template_name = "your_template.html" def get_queryset(self): # 必须先排序,groupby才能正确分组! return super().get_queryset().order_by("category", "name") def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 按category字段分组,转成列表(避免迭代器在模板里循环多次失效) grouped_items = groupby(context["object_list"], key=lambda x: x.category) context["grouped_items"] = [(category, list(items)) for category, items in grouped_items] return context
模板代码
{% for category, items in grouped_items %} <h2>{{ category.name }}</h2> {% for item in items %} <div class="list-item">{{ item.title }}</div> {% endfor %} {% endfor %}
这两种方法都不用写任何自定义过滤器或标签,完全用Django自带的功能就能搞定,是不是比你想的简单多了?
内容的提问来源于stack exchange,提问作者NaturalBornCamper
相关产品推荐
相关产品推荐

