Django通过查询集中的唯一值获取总计数和计数
Posted
技术标签:
【中文标题】Django通过查询集中的唯一值获取总计数和计数【英文标题】:Django get total count and count by unique value in queryset 【发布时间】:2021-01-02 06:28:58 【问题描述】:我的模型 Software
和 Domain
大致描述为:
class Software(models.Model)
id = models.BigInteger(primary_key=True, db_index=True, null=False)
company = models.ForeignKey('Company')
domain = models.ForeignKey('Domain')
type = models.CharField(null=False)
vendor = models.CharField(null=False)
name = models.CharField(null=False)
class Domain(models.Model):
id = models.BigInteger(primary_key=True, db_index=True, null=False)
type = models.CharField()
importance = models.DecimalField(max_digits=11, decimal_places=10, null=False)
我得到一个 Software
查询集:
qs = Software.objects.filter(company=c).order_by('vendor')
所需的输出应具有聚合的 Domain
重要性以及每个唯一 Software
的总计数,即
[
'type': 'type_1', \
'vendor': 'ajwr', | - unique together
'name': 'nginx', /
'domains':
'total_count': 4,
'importance_counts': [0.1: 1, 0.5: 2, 0.9: 1] # sum of counts = total_count
,
,
...
,
]
我觉得这里的第一步应该是将type, vendor, name
分组Domain
这样每个Software
对象都有一个Domains
列表而不是一个列表,但我不知道该怎么做.在内存中执行此操作会更容易,但似乎比使用查询集/SQL 慢很多。
【问题讨论】:
这看起来更像是序列化程序的工作(就像你说的,在 python 中做)但是为了确保你避免做很多数据库查询,你应该使用.prefetch_related('domain')
我认为 WRT 在内存中这样做是对的——尽管我觉得在 Domain
back 到 Software
上存在一对多关系,它可以在单独的查询集
【参考方案1】:
所以我会这样做:
from django.db.models import Sum
qs = Software.objects.filter(company=c).prefetch_related(
'domain'
).annotate(
total_count=Sum('domain__importance')
).order_by('vendor')
output = []
for obj in qs:
domains = obj.domain.all() # using prefetched domains, no db query
output.append(
# ...
'domains':
'total_count': obj.total_count,
'importance_counts': [d.importance for d in domains]
)
而且我相信它应该足够快。只有当发现它不是我会尝试改进。记住“过早的优化是万恶之源”
【讨论】:
以上是关于Django通过查询集中的唯一值获取总计数和计数的主要内容,如果未能解决你的问题,请参考以下文章