You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django模板循环优化:实现参与者仅显示一次并关联所有投票者

解决Django中重复显示参与者并聚合投票者的问题

问题场景

现有Participanti(被投票者)和Restrictie(投票记录)模型,Restrictie记录了被投票者与投票者的关联。在模板中直接遍历Restrictie所有数据时,同一参与者会随每条投票记录重复显示,期望实现每个参与者仅显示一次,旁侧列出所有对应的投票者,格式如「参与者姓名 -(投票者1姓名,投票者2姓名……)」。

现有代码

models.py

class Participanti(models.Model):
    campanievot = models.ForeignKey(Campanie, on_delete=models.CASCADE)
    nume_participant = models.CharField(max_length=200, verbose_name='nume')
    dep_participant = models.CharField(max_length=200, verbose_name='departament')
    votes = models.IntegerField(default=0)
    
    def __str__(self):
        return self.nume_participant

    class Meta:
        verbose_name = 'Participanti'
        verbose_name_plural = 'Participanti'


class Restrictie(models.Model):
    participanti = models.ForeignKey(Participanti,on_delete=models.CASCADE, verbose_name='Votat')
    votant = models.ForeignKey(UserVot,on_delete=models.CASCADE)

    def __str__(self):
        return str(self.participanti)

    class Meta:
        verbose_name = 'Voturi efectuate'
        verbose_name_plural = 'Voturi efectuate'

views.py

def rezultate(request):
    cineavotat = Restrictie.objects.all()
    # 其他逻辑...
    return render(request, 'your_template.html', {'cineavotat': cineavotat})

原模板代码(存在重复问题)

{% for p in cineavotat %}  
  {{ p.participanti }} - {{ p.votant}}
{% endfor %}

解决方案

方案1:使用Django模板regroup标签(无需修改视图)

利用Django内置的regroup标签,直接在模板中按参与者分组,无需改动视图层代码:

{% regroup cineavotat by participanti as participanti_groups %}

{% for group in participanti_groups %}
  {{ group.grouper.nume_participant }} - (
    {% for restrictie in group.list %}
      {{ restrictie.votant }}{% if not forloop.last %}, {% endif %}
    {% endfor %}
  )
{% endfor %}
  • regroup cineavotat by participanti as participanti_groups:将所有投票记录按participanti字段分组,得到以参与者为键、对应投票记录列表为值的分组集合
  • group.grouper:代表分组的参与者对象,直接调用nume_participant获取姓名
  • 内层循环遍历该参与者的所有投票记录,提取投票者姓名并拼接格式

方案2:视图层预聚合数据(性能更优)

如果数据量较大,推荐在视图层通过ORM预获取并聚合数据,减少模板层的逻辑处理,提升性能:

修改views.py

from django.db.models import Prefetch

def rezultate(request):
    # 预获取每个参与者对应的所有投票记录,并关联查询投票者信息
    participanti_list = Participanti.objects.prefetch_related(
        Prefetch(
            'restrictie_set', 
            queryset=Restrictie.objects.select_related('votant'),
            to_attr='votanti_list'
        )
    ).all()
    return render(request, 'your_template.html', {'participanti_list': participanti_list})
  • prefetch_related:预加载参与者关联的所有Restrictie记录
  • select_related('votant'):同时关联查询投票者的用户信息,避免N+1查询
  • to_attr='votanti_list':将关联的投票记录存入自定义属性,方便模板调用

对应模板代码

{% for participant in participanti_list %}
  {{ participant.nume_participant }} - (
    {% for restrictie in participant.votanti_list %}
      {{ restrictie.votant }}{% if not forloop.last %}, {% endif %}
    {% endfor %}
  )
{% endfor %}

内容的提问来源于stack exchange,提问作者Robert Murariu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:30:57