前端提了个需求,需要统计各版本的使用情况。在网上搜寻一番,发现aggregate和annotate方法可以很简单的实现这个功能,在使用过程中遇到了个坑,就是无论是按照官方的帮助文档,还是各大论坛的教程,都不能获取到正确的结果。
网上千篇一律的写法大致是这样的。
Student.objects.values('name').annotate(Count('hobbies'))
或者是这样的:
Student.objects.annotate(hobby_count=Count('hobbies')).values('name', 'hobby_count')
官方的教程是这样的:
pubs=Publisher.objects.annotate(num_books=Count('book'))
这些语句在实际环境里面就是执行不了,执行得到的都是没有分组的结果,并没有起到统计的作用。
定位这个问题最后还是用到了SQL语句,在上述语句后面使用.query属性可获得对应的SQL语句,如下是调试时打印的SQL语句:
SELECT `testbench_testbench`.`location`, COUNT(`testbench_testbench`.`version`) AS `a` FROM `testbench_testbench` GROUP BY `testbench_testbench`.`location`, `testbench_testbench`.`created_time` ORDER BY `testbench_testbench`.`created_time` ASC
可以发现 group by后面有两个字段,一个是location,一个是created_time。此是因为我们在定义models时定义了ordering属性,至此原因明确了,在语句中加上一段去除group by的默认设置即可,其方法是添加.order_by()方法,如:
TestBench.objects.order_by('version').values('version').annotate(num=Count('version')).values('version','num')
总结
对于Django数据库的操作如果出现一些奇怪的问题,可以打印出SQL语句,根据SQL语句分析问题的关键点,找出对应方法。
网友评论