Django如何基于另一张表的字段值过滤数据并统计关联记录数量
现有代码问题说明
你当前写法中Meter_Mapping_Table.objects.filter(DCU_id=dcu.id).count()是错误的:dcu是模型类而非具体实例,dcu.id拿到的是模型字段对象,不是某条dcu记录的id值,无法实现按单条dcu记录id匹配统计的需求。
正确实现方案
分两种常见场景提供方案:
场景1:需要给所有返回的dcu记录,各带对应的关联计数
推荐用Django ORM的annotate注解实现,仅需1次数据库查询,性能远高于循环查询:
from django.db.models import Count, OuterRef, Subquery, IntegerField def dcuinterval(request): # 构造子查询:统计每个dcu id对应的匹配记录数 count_subquery = Meter_Mapping_Table.objects.filter( DCU_id=OuterRef('id') # 关联外层dcu表的id字段 ).values('DCU_id').annotate( cnt=Count('*') ).values('cnt') # 给每个dcu实例追加MU_count属性,无匹配记录时值为null var7 = dcu.objects.annotate( MU_count=Subquery(count_subquery, output_field=IntegerField()) ).all() return render(request, 'dcu_interval.html', {'var7': var7})
模板中使用方式:
{% for dcu_item in var7 %} <p>DCU编号:{{dcu_item.id}},关联Meter条数:{{dcu_item.MU_count|default:0}}</p> {% endfor %}
注:加|default:0是为了处理无匹配记录时返回null的情况,默认显示0
场景2:仅统计指定单个dcu的关联条数
如果请求时会传入指定的dcu id参数,写法如下:
def dcuinterval(request): var7 = dcu.objects.all() MU_count = 0 # 从请求参数中取需要查询的dcu id,参数名可根据实际调整 target_dcu_id = request.GET.get('dcu_id') if target_dcu_id: # 注意Meter_Mapping_Table的DCU_id是字符串类型,需和入参类型匹配 MU_count = Meter_Mapping_Table.objects.filter(DCU_id=target_dcu_id).count() return render(request, 'dcu_interval.html', {'var7': var7, 'MU_count': MU_count})
可选优化建议
如果业务逻辑上Meter_Mapping_Table的DCU_id就是关联dcu表的id,建议把该字段改成外键类型,后续关联查询会更简洁:
# 修改models.py中Meter_Mapping_Table的DCU_id字段定义 class Meter_Mapping_Table(models.Model): # 其他原有字段保持不变 DCU = models.ForeignKey( dcu, on_delete=models.SET_NULL, # 可根据业务需求调整删除关联规则 null=True, blank=False, db_column='DCU_id' # 保持数据库字段名不变,避免数据迁移问题 )
修改后统计所有dcu的关联计数仅需一行代码:
var7 = dcu.objects.annotate(MU_count=Count('meter_mapping_table')).all()
内容的提问来源于stack exchange,提问作者kabilan kabi
相关产品推荐
相关产品推荐

