Django ORM 知识点总结 (2)

一个query只能有一个order_by,如果有多个,后面的order_by会覆盖前面的,如

Order.objects.order_by('project_id').order_by('name') # sql: # select * from order order by order.name ASC

对bool值按默认顺序排序的时候,False会排在True前面,因为False相当于0,True相当于1

# 需要将True排在前面 def test_order_by(): result = OrderLanguagePair.objects.order_by('-activate').first() print(result.activate) group by

比如现在想知道每个项目有多少个订单,在sql语句中应对订单按项目id分组,然后求出每组订单的数量

SELECT project_id, count(*) FROM order group by project_id;

django ORM中没有显式的group by函数,通过annotate来实现分组

# annotate的作用是为一个query增加一个自定义的新字段 # annotate接收表达式作为参数 def annotate(self, *args, **kwargs): """ Return a query set in which the returned objects have been annotated with extra data or aggregations. """

如果没有指定任何字段,annotate会根据前面queryset的第一个字段(一般是id)分组计算,如

Order.objects.annotate(Count('name')) # sql: # select *, count(order.name) from order group by order.id

在annotate前用values或values_list指定根据什么字段分组,如

# 注意values要放在annotate之前 Order.objects.values('project_id').annotate(count=Count('*')) # sql: # select order.project_id, count(*) as count from order group by order.project_id

annotate定义的字段会加到前面的values或values_list中

values中有多个值时,会按照顺序group by

Order.objects.values('project_id', 'name').annotate(count=Count('*')) # sql: # select order.project_id, order.name, count(*) as count from order group by order.project_id, order.name

如果annotate所属的query含有order_by的话,除了按values的字段分组外,还会额外按照order_by的字段分组(如果order_by中的字段不在values中)

# 下面两个query对应的sql是一样的 Order.objects.values('project_id').annotate(count=Count('*')).order_by('name') Order.objects.order_by('name').values('project_id').annotate(count=Count('*')) # sql: # select order.project_id, count(*) as count from order # group by order.project_id, order.name # order by order.name

解决的方法是用对分组字段的排序覆盖query之前的排序,比如

query = Order.objects.order_by('name') query.order_by('project_id').values('project_id').annotate(count=Count('*')) 别名

希望使用ORM实现给字段加别名,如

select name as user_name, id as user_id from users

Django有两种实现方式

extra

User.objects.extra(select={'user_id':user, 'user_name':id}). \ values('user_id', 'user_name')

但是这种方法只能适用于没有外键引用的情况,即只能选择给此Model的字段取别名,如果要给外键引用的字段取别名,需要用到下面这种方式

annotate

ProjectLanguagePair.objects.\ annotate(supplier_name=F('supplier__supplier_name')). \ values('supplier_name')

ProjectLanguagePair用supplier字段外键到了Supplier表,相当于

SELECT `supplier_app_supplier`.`supplier_name` AS `supplier_name`

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxspz.html