Django模板计数器无法累加求助:统计每个侵权者的侵权次数
问题解决:Django模板中侵权者侵权行为计数无法累加
问题描述
尝试统计每个侵权者的侵权行为总数时,使用{{ a|add:"1" }}标签输出结果为1 1 1,而非预期的总数3,计数器无法正常累加。
原因分析
Django模板中的变量是不可变的,add过滤器仅返回计算后的新值,不会修改原变量a的初始值(此处为0)。每次循环执行{{ a|add:"1" }}时,都是基于初始的0加1得到1,而非在上一次的结果上累加,因此会重复输出1。
解决方案
方案1:视图层预处理(推荐,性能更优)
直接在数据库查询阶段统计每个侵权者的侵权行为数量,避免模板中冗余的循环判断。
修改views.py代码,使用annotate和Count聚合函数:
from django.db.models import Count, Q from django.contrib.auth.decorators import login_required @login_required(login_url='login') def infringerlist(request): q = request.GET.get('q') or '' # 为每个侵权者标注对应的侵权行为数量 ings = Infringer.objects.filter( Q(created__icontains=q) | Q(id__icontains=q) | Q(status__name__icontains=q) | Q(brand_name__icontains=q) | Q(name__icontains=q), customer=request.user.customer, ).annotate(infringement_count=Count('infringement')) # 注意:这里的'infringement'需和Infringement模型中指向Infringer的外键反向关联名一致,若外键字段名为infringer,默认反向名就是infringement paginator = Paginator(ings, 10) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) context = {'page_obj': page_obj} return render(request,'base/infringers_list.html', context)
模板中直接调用统计好的字段即可,无需内层循环:
{% for infringer in page_obj %} <tr> <td>{{ infringer.id }}</td> <td>{{ infringer.created|date:"d M, Y" }}</td> <td>{{ infringer.name }}</td> <td>{{ infringer.brand_name }}</td> <td>{{ infringer.status }}</td> <td>{{ infringer.infringement_count }}</td> </tr> {% endfor %}
方案2:模板层自定义过滤器(应急方案,性能较差)
若暂时无法修改视图逻辑,可通过自定义模板过滤器过滤出当前侵权者的所有侵权行为,再取长度得到总数。
- 在你的Django应用下创建
templatetags目录,新建custom_filters.py文件:
from django import template register = template.Library() @register.filter def filter_by_infringer(infringements, infringer_id): # 过滤出属于当前侵权者的所有侵权行为 return [inc for inc in infringements if inc.infringer.id == infringer_id]
- 在模板开头加载自定义过滤器:
{% load custom_filters %}
- 修改模板中的计数逻辑:
{% for infringer in page_obj %} <tr> <td>{{ infringer.id }}</td> <td>{{ infringer.created|date:"d M, Y" }}</td> <td>{{ infringer.name }}</td> <td>{{ infringer.brand_name }}</td> <td>{{ infringer.status }}</td> <td> {% with matched_inc=inc|filter_by_infringer:infringer.id %} {{ matched_inc|length }} {% endwith %} </td> </tr> {% endfor %}
注意:此方案需要遍历所有侵权行为数据,当数据量较大时会显著影响页面性能,优先推荐方案1。
内容的提问来源于stack exchange,提问作者Farid
相关产品推荐
相关产品推荐

