Django 仅显示对象一次并对其进行计数

Django 仅显示对象一次并对其进行计数,django,Django,在寻找了很长时间而没有得到答案后,我将在这里尝试 我在做django。我的项目是一个邮件系统,每次收件人打开邮件时,我都知道打开的是什么邮件,是谁打开的,什么时候打开的。 这是我显示统计数据的表格。它向我显示了每个收件人和日期时间,但我的问题是我想看到每个收件人一次,然后显示它被打开了多少次 <tbody> {% for stat_mail in stat_mail %} {% ifchanged stat_mail.rec

在寻找了很长时间而没有得到答案后,我将在这里尝试

我在做django。我的项目是一个邮件系统,每次收件人打开邮件时,我都知道打开的是什么邮件,是谁打开的,什么时候打开的。 这是我显示统计数据的表格。它向我显示了每个收件人和日期时间,但我的问题是我想看到每个收件人一次,然后显示它被打开了多少次

        <tbody>
          {% for stat_mail in stat_mail %}
            {% ifchanged stat_mail.recipient %}
              <tr>
                  <td>{{ stat_mail.recipient }}</td>
                  <td>{{ stat_mail.datetime }}</td>
                  <td>{{ stat_mail.recipient_set.all|length }}</td>
              </tr>
            {% endifchanged %}
          {% endfor %}
        </tbody>

您应该在视图中准备数据,然后将其传递给模板。类似这样(未经测试):

然后在模板中,您可以简单地执行以下操作:

<tbody>
    {% for r in recipient_list %}
        <tr>
            <td>{{ r.recipient }}</td>
            <td>
                <ul>
                {% for dt in r.read_datetime_list %}
                    <li>{{ dt }}</li>
                {% endfor %}
                </ul>
            </td>
            <td>{{ r.cnt_read }}</td>
        </tr>
    {% endfor %}
</tbody>

{收件人_列表%r中的%r}
{{r.recipient}}
    {r.read_datetime_list%中dt的%
  • {{dt}}
  • {%endfor%}
{{r.cnt_read}} {%endfor%}

重要的是:不要在模板中费力地做复杂的事情,只保留它们用于演示目的。将视图中的所有逻辑(或模型或实用程序模块)移动到视图中,您就可以充分利用Python的所有功能。

那么,您看到了什么而不是期望看到的?这将有助于显示模型。表格应该显示不同的收件人(没有重复的收件人),并计算一个收件人打开邮件的次数。我在问题上添加了我的模型。实际上,每次收件人在表格中时,它都会显示收件人,但不计算。更好的数据结构应该是字典;由于密钥是收件人。这很有效。谢谢,唯一的问题是表中最后一个收件人没有进入列表,因此不会显示在表中。因为它从不进入:if stat.recipient!=当前收件人:如果有人知道如何修复它?但真的很感谢,它帮了我很多!编辑:我更改了代码,只是在末尾添加了.append,所以每次列表都会有一个新条目,然后在模板上使用了一个ifchanged。但是我认为一个更好的解决方案是,我编辑代码时考虑到查询集的最后一个接收者。对于第一个版本中的错误,很抱歉,所有代码都应该经过测试;)。它工作了谢谢,你不必为它的工作而感到抱歉:)
from django.shortcuts import render

from .models import Mail_Stats

def stats_view(request):
    recipient_list = [] # this will be put in the template context

    current_recipient = None
    cnt_read = 0
    read_datetime_list = []

    for stat in Mail_Stats.objects.all().order_by('mail', 'recipient'):
        if stat.recipient != current_recipient:
            if cnt_read > 0:
                recipient_list.append({
                    'recipient': current_recipient,
                    'read_datetime_list': read_datetime_list,
                    'cnt_read': cnt_read
                })
            current_recipient = stat.recipient
            cnt_read = 0
            read_datetime_list = []
        cnt_read += 1
        read_datetime_list.append(stat.datetime)

    # add last recipient to the list, if not None
    if current_recipient is not None:
        recipient_list.append({
            'recipient': current_recipient,
            'read_datetime_list': read_datetime_list,
            'cnt_read': cnt_read
        })

    render(request, 'mail_stats.html', { 'recipient_list': recipient_list })
<tbody>
    {% for r in recipient_list %}
        <tr>
            <td>{{ r.recipient }}</td>
            <td>
                <ul>
                {% for dt in r.read_datetime_list %}
                    <li>{{ dt }}</li>
                {% endfor %}
                </ul>
            </td>
            <td>{{ r.cnt_read }}</td>
        </tr>
    {% endfor %}
</tbody>