如何在Django中统计枚举字段各选项的条目数量?
统计Django枚举字段各值的条目数量(最优方案)
你的Django模型代码:
class Menu(models.Model): class placeMenu(models.TextChoices): navar_menu_1="MN1", ("چایگاه هدر اول") navar_menu_2="MN2", ("جایگاه هدر دوم") navar_menu_3="MN3", ("جایگاه هدر سوم") footer_menu_1="FN1", ("جایگاه فوتر اول") footer_menu_2="FN2", ("جایگاه فوتر دوم") social = "SC1", ("شبکه های اجتماعی") title=models.CharField(max_length=50) url=models.URLField(max_length=50) sort=models.IntegerField() is_active=models.BooleanField(default=1) icon_name=models.CharField(max_length=50,blank=False,null=True) icon_color=models.CharField(max_length=50,blank=False,null=True) place_menu=models.CharField(max_length=50,choices=placeMenu.choices) def __str__(self): return self.title
最优统计方案(数据库层面聚合)
直接利用Django ORM的values()和annotate()在数据库完成分组计数,无需加载全量数据到内存,性能最优:
1. 基础统计(仅返回有数据的枚举值)
from django.db.models import Count # 按place_menu分组,统计每组的条目数 menu_counts = Menu.objects.values('place_menu').annotate(count=Count('id')).order_by('place_menu')
返回结果是类似[{'place_menu': 'MN1', 'count': 3}, {'place_menu': 'FN1', 'count': 5}, ...]的查询集。
2. 关联枚举显示名称(波斯语标签)
如果需要把枚举值(如MN1)映射为对应的友好名称,可以先构建值与标签的映射,再转换结果:
# 构建枚举值到波斯语标签的映射 place_menu_label_map = {value: label for value, label in Menu.placeMenu.choices} # 转换为带标签的统计字典 count_result = { place_menu_label_map[item['place_menu']]: item['count'] for item in menu_counts }
最终得到类似{'چایگاه هدر اول': 3, 'جایگاه فوتر اول': 5, ...}的字典。
3. 包含所有枚举值(无数据的显示0)
如果需要统计所有枚举值,哪怕该值没有对应条目(计数为0),可以先初始化全量枚举的计数,再更新实际统计结果:
# 初始化所有枚举值的计数为0 full_count = {label: 0 for _, label in Menu.placeMenu.choices} # 更新有数据的枚举值计数 for item in menu_counts: full_count[place_menu_label_map[item['place_menu']]] = item['count']
方案优势
这种方式直接在数据库层面完成聚合计算,只返回统计后的少量数据,相比把所有Menu实例加载到内存再循环统计,在数据量较大时性能提升非常明显,是Django中处理这类统计的最优实践。
内容的提问来源于stack exchange,提问作者alireza keshavarz
相关产品推荐
相关产品推荐

