Django PDF模板按地址统计事故严重程度行数实现方法问询
实现按地址统计事故严重程度的报表
方法一:使用Django ORM聚合查询(推荐)
利用Django的ORM聚合功能,直接在数据库层面完成分组统计,效率更高。
1. 视图层代码
假设你的事故模型(Accident)包含address(地址)和severity(事故严重程度)字段,在视图中编写如下逻辑:
from django.db.models import Count, Case, When, IntegerField from django.shortcuts import render from .models import Accident def accident_report(request): # 按地址分组,分别统计三种严重程度的事故数量 address_stats = Accident.objects.values('address').annotate( fatal_count=Count(Case( When(severity='Fatal', then=1), output_field=IntegerField(), )), non_fatal_count=Count(Case( When(severity='Non-Fatal', then=1), output_field=IntegerField(), )), property_damage_count=Count(Case( When(severity='Damage to Property', then=1), output_field=IntegerField(), )) ).order_by('address') return render(request, 'accident_report.html', {'address_stats': address_stats})
2. 模板层代码(accident_report.html)
将统计结果渲染为可视化表格:
<!DOCTYPE html> <html> <head> <title>事故统计报表</title> <style> table { border-collapse: collapse; width: 100%; margin-top: 20px; } th, td { border: 1px solid #ddd; padding: 10px; text-align: left; } th { background-color: #f5f5f5; } </style> </head> <body> <h2>按地址统计事故严重程度</h2> <table> <thead> <tr> <th>地址</th> <th>致命事故(Fatal)</th> <th>非致命事故(Non-Fatal)</th> <th>财产损失事故(Damage to Property)</th> <th>总计</th> </tr> </thead> <tbody> {% for stat in address_stats %} <tr> <td>{{ stat.address }}</td> <td>{{ stat.fatal_count }}</td> <td>{{ stat.non_fatal_count }}</td> <td>{{ stat.property_damage_count }}</td> <td>{{ stat.fatal_count|add:stat.non_fatal_count|add:stat.property_damage_count }}</td> </tr> {% empty %} <tr> <td colspan="5">暂无事故数据</td> </tr> {% endfor %} </tbody> </table> </body> </html>
方法二:手动分组统计(适合复杂场景)
如果ORM聚合无法满足特殊逻辑需求,可以在视图中手动处理数据:
from django.shortcuts import render from .models import Accident from collections import defaultdict def accident_report(request): # 初始化统计字典:键为地址,值为各严重程度的计数 stats = defaultdict(lambda: {'Fatal': 0, 'Non-Fatal': 0, 'Damage to Property': 0}) # 遍历所有事故数据,更新计数 for accident in Accident.objects.all(): stats[accident.address][accident.severity] += 1 # 转换为列表并按地址排序,方便模板遍历 address_stats = [ { 'address': addr, 'fatal_count': data['Fatal'], 'non_fatal_count': data['Non-Fatal'], 'property_damage_count': data['Damage to Property'] } for addr, data in sorted(stats.items()) ] return render(request, 'accident_report.html', {'address_stats': address_stats})
模板代码与方法一完全通用。
关键注意事项
- 确保
Accident模型中severity字段的取值与你定义的三种类型完全匹配(包括大小写、空格),否则统计会出现偏差。 - 如果存在地址格式不统一的情况(如"Main St"和"Main Street"),需先对地址进行标准化处理,避免重复统计。
- 若要将报表导出为PDF,可基于现有视图逻辑,使用WeasyPrint等库将模板渲染为PDF文件返回。
内容的提问来源于stack exchange,提问作者kimski
相关产品推荐
相关产品推荐

