在 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 clause 和 annotate
,例如:
>>> 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)
我正在使用 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 clause 和 annotate
,例如:
>>> 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)