如何在Django中跨3个模型聚合数据并渲染至HTML模板
Django 按主机分组汇总漏洞数据的解决方案
先确认模型关联(按需调整字段)
假设你的模型结构如下,确保ClientVULDB的外键关联正确设置related_name:
class ClientDB(models.Model): hostname = models.CharField(max_length=100, unique=True) # 其他主机字段(如IP、操作系统等) class VULDB(models.Model): title = models.CharField(max_length=200) # 其他漏洞字段(如CVE编号、风险等级等) class ClientVULDB(models.Model): client = models.ForeignKey(ClientDB, on_delete=models.CASCADE, related_name='vul_relations') vul = models.ForeignKey(VULDB, on_delete=models.CASCADE) # 可选字段:扫描时间、修复状态等
视图实现方案
方案1:用Django聚合函数(推荐,适合PostgreSQL)
利用StringAgg直接在数据库层面完成分组聚合,效率更高:
from django.db.models import StringAgg from django.shortcuts import render from .models import ClientDB def host_vul_summary(request): # 按主机分组,聚合去重后的漏洞标题,用顿号分隔 host_vuls = ClientDB.objects.annotate( vul_titles=StringAgg('vul_relations__vul__title', delimiter='、', distinct=True) ).all() return render(request, 'vul_summary.html', {'host_vuls': host_vuls})
注:如果用MySQL,需要安装django-mysql包,替换StringAgg为GroupConcat
方案2:手动分组(兼容所有数据库,更灵活)
通过遍历主机,逐个获取关联漏洞,适合需要额外处理逻辑的场景:
from django.shortcuts import render from .models import ClientDB def host_vul_summary(request): host_vul_list = [] for client in ClientDB.objects.all(): # 获取该主机关联的所有去重漏洞标题 vul_titles = client.vul_relations.values_list('vul__title', flat=True).distinct() host_vul_list.append({ 'hostname': client.hostname, 'vul_titles': vul_titles }) return render(request, 'vul_summary.html', {'host_vul_list': host_vul_list})
模板渲染
根据选择的视图方案,对应编写HTML模板:
对应方案1的模板:
{% for host in host_vuls %} <div> <strong>{{ host.hostname }}</strong> 对应 {{ host.vul_titles|default:"无漏洞" }} </div> {% endfor %}
对应方案2的模板:
{% for item in host_vul_list %} <div> <strong>{{ item.hostname }}</strong> 对应 {% for title in item.vul_titles %} {{ title }}{% if not forloop.last %}、{% endif %} {% empty %} 无漏洞 {% endfor %} </div> {% endfor %}
关键注意事项
- 确保
ClientVULDB的client字段设置了related_name='vul_relations',否则无法通过主机对象直接关联漏洞关系 - 使用
distinct()避免同一主机重复显示相同漏洞标题 - 如果需要按漏洞风险等级过滤,可在查询集里添加
filter(vul_relations__vul__severity='高危')这类条件
内容的提问来源于stack exchange,提问作者xMonkey1337
相关产品推荐
相关产品推荐

