返回
Django 表单中如何在一行中显示唯一项目的金额汇总?
python
2024-03-21 07:27:38
Django 表单:单行中的唯一项目
问题:
我们在使用 Django 的 HTML 表单时,遇到这样的问题:需要在一行中获取所有金额,但“类别名称”不再唯一,因为它由月份注释。
解决方法:
为了解决此问题,我们可以使用 collections.defaultdict
将类别名称作为键,将月份作为子键,并将金额作为值。然后,我们可以使用字典推导来遍历按类别名称和月份分组的总和,并创建带有每月金额和总金额的 CategoryOverview
对象。
from collections import defaultdict
from django.db.models import Sum
from django.db.models.functions import ExtractMonth
from django.shortcuts import render
from django.views.generic import TemplateView
class CashFlow(LoginRequiredMixin, AccountContextMixin, TemplateView):
model = Transaction
template_name = 'transaction_app/cf.html'
context_object_name = 'transaction'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = self.request.user
# 代码 ...
items = defaultdict(dict)
sum_per_month = (
Transaction.objects.filter(
user=user,
transaction_date__year=selected_year,
status=selected_status,
)
.values(
month=ExtractMonth('transaction_date'),
category_name=F('category__category_name'),
)
.annotate(total_amount=Sum('amount'))
.order_by('category_name', 'month')
)
for record in sum_per_month:
items[record['category_name']][record['month']] = record['total_amount']
context['summary'] = [
CategoryOverview(key, [entries.get(month) for month in range(1, 13)], sum(entries)
)
for key, entries in items.items()
]
return context
HTML 模板:
{% for item in summary %}
<tr>
<td>{{ item.category_name }}</td>
{% for amount in item.monthly_amounts %}
<td>{{ amount }}</td>
{% endfor %}
<td>{{ item.total_amount }}</td>
</tr>
{% endfor %}
总结:
通过使用 defaultdict
,我们可以创建一行中显示所有金额的表格,即使“类别名称”不再唯一。这使我们能够在单行中轻松查看每个类别的总金额和每月金额。
常见问题解答:
-
为什么使用
defaultdict
?defaultdict
使我们可以创建嵌套字典,其中不存在的键将被自动创建并设置为默认值(在这种情况下为dict
)。这使我们可以方便地跟踪每个类别的每月金额。
-
CategoryOverview
对象有什么作用?CategoryOverview
对象使我们可以将每个类别的每月金额和总金额打包成一个单一的、易于使用的对象。
-
为什么使用月份来对结果进行排序?
- 对结果按月份排序可确保每月金额按顺序显示,使表格易于阅读。
-
如何处理没有特定月份的类别?
- 如果某个类别没有特定月份的记录,则可以在 HTML 模板中使用
{% if amount %} ... {% endif %}
来仅显示有记录的月份。
- 如果某个类别没有特定月份的记录,则可以在 HTML 模板中使用
-
如何在模板中动态创建列?
- 可以在 HTML 模板中使用
{% for amount in item.monthly_amounts %} ... {% endfor %}
循环来动态创建列,根据类别的每月金额数量自动调整表格的宽度。
- 可以在 HTML 模板中使用