在 Django Like 和 Excel 文件中查找数据列的总和

Find Sum of Columns of Data in Django Like and Excel File

我正在使用 Django 1.8.3 和 Python 3.4.3

将我的问题与 Excel 文件进行比较是我解释挑战的最佳方式。我有一个 ListView,它在我的模板中显示 table 数据。左列是一月到十二月,顶部有值字段(就像 Excel 电子表格)我需要添加 "columns" 的值以呈现 "total" 总和。我已经阅读了几种解决方案,但我似乎无法弄清楚这是一种 Pythonic 方式。

下面是我的代码片段,希望它们能让您更好地了解我需要做什么。

需要的解决方案:我需要获取每个月收件人的总价值table,这将显示在主矩阵中(此处未显示)

感谢您的帮助。如果您有帮助,请同时提供模板标签示例。

index.html(仅显示 1 月和 2 月,但列表显示到 12 月)

<thead>
  <tr>
    <th></th>
    <th>Quantity</th>
    <th>Recipients</th>
    <th>Unsubscribes</th>
    <th>Bounces</th>
    <th>Open</th>
    <th>Clicks</th>
    <th>Open Rate</th>
    <th>CTR</th>
    <th>Sales</th>
    <th>IFS SignUps</th>
    <th>Traffic</th>
    <th>T/S Ratio</th>
  </tr>
</thead>
<tbody>
  <tr>
    {% if email_list %}
      <td>January</td>
      <td>{{ total_campaigns.January | default_if_none:"0" }}</td>
      <td>{{ total_recipients.January | default_if_none:"0" }}</td>
      <td>{{ total_unsubscribes.January | default_if_none:"0" }}</td>
      <td>{{ total_bounces.January | default_if_none:"0" }}</td>
      <td>{{ total_open.January | default_if_none:"0" }}</td>
      <td>{{ total_clicks.January | default_if_none:"0" }}</td>
      <td>{% average total_open.January total_recipients.January %}</td>
      <td>{% average total_clicks.January total_open.January %}</td>
    {% endif %}
    {% if traffic_list %}
      <td>{{total_sales.January | default_if_none:"0" }}</td>
      <td>{{total_ifs_signups.January | default_if_none:"0" }}</td>
      <td>{{total_traffic.January | default_if_none:"0" }}</td>
      <td>{% ratio total_traffic.January total_sales.January %}</td>
    {% endif %}
  </tr>
  <tr>
    {% if email_list %}
      <td>February</td>
      <td>{{ total_campaigns.February | default_if_none:"0" }}</td>
      <td>{{ total_recipients.February | default_if_none:"0" }}</td>
      <td>{{ total_unsubscribes.February | default_if_none:"0" }}</td>
      <td>{{ total_bounces.February | default_if_none:"0" }}</td>
      <td>{{ total_open.February | default_if_none:"0" }}</td>
      <td>{{ total_clicks.February | default_if_none:"0" }}</td>
      <td>{% average total_open.February total_recipients.February %}</td>
      <td>{% average total_clicks.February total_open.February %}</td>
    {% endif %}
    {% if traffic_list %}
      <td>{{total_sales.February | default_if_none:"0" }}</td>
      <td>{{total_ifs_signups.February | default_if_none:"0" }}</td>
      <td>{{total_traffic.February | default_if_none:"0" }}</td>
      <td>{% ratio total_traffic.February total_sales.February %}</td>
    {% endif %}
  </tr>

  ... ( This repeats through the month of December )

views.py(我的视图文件中的示例数据)

    class DashboardView(TemplateView):
        template_name = "dashboard/pages/index.html"

        def get_context_data(self, **kwargs):
            context = super(DashboardView, self).get_context_data(**kwargs)
            context['email_list'] = Email.objects.all()
            context['traffic_list'] = Traffic.objects.all()

            days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
            months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October',
                      'November', 'December']

            total_campaigns = {}
            campaign_totals = {}
            total_recipients = {}
            total_unsubscribes = {}
            total_bounces = {}
            total_open = {}
            total_clicks = {}
            total_sales = {}
            total_ifs_signups = {}
            total_traffic = {}

            for month in months:
                # total count
                total_campaigns[month] = Email.objects.filter(month=month).count()
                # recipients
                total_recipients[month] = Email.objects.filter(month=month).aggregate(
                    Sum('recipients')).get('recipients__sum', 0.00)
                # unsubscribes
                total_unsubscribes[month] = Email.objects.filter(month=month).aggregate(
                    Sum('unsubscribes')).get('unsubscribes__sum', 0.00)
                # bounces
                total_bounces[month] = Email.objects.filter(month=month).aggregate(Sum('bounces')).get(
                    'bounces__sum', 0.00)
                # opens
                total_open[month] = Email.objects.filter(month=month).aggregate(
                    Sum('open')).get('open__sum', 0.00)
                # clicks
                total_clicks[month] = Email.objects.filter(month=month).aggregate(
                    Sum('clicks')).get('clicks__sum', 0.00)

...

Django aggregation支持这个。

对于按字段分组的聚合,使用 values clauseannotate ,例如:

>>> from django.db.models import Count, Sum

>>> stats = Email.objects.all().values('month').annotate(
        Count('month'), Sum('recipients'), Sum('unsubscribes'), ...)
>>> stats
[{'month': 'January', 'month__count': 100, 'recipients__sum': 24, ... }
 {'month': 'February', 'month__count': 75, 'recipients__sum': 22, ... }]

您还可以使用 aggregate:

从数据库中获取总计
>>> Email.objects.all().aggregate(
        Count(), Sum('recipients'), Sum('unsubscribes'), ...)

{'id__count': 175, 'recipients__sum': 46, ...}

但是,避免再次查询数据库并根据内存中已有的内容计算总计(按月聚合)可能会更快:

>>> totals = {}
>>> for key in ['month__count', 'recipients__sum', 'unsubscribes__sum', ...]:
...     totals[key] = sum(month.get(key, 0) for month in stats)