Django之ORM操作(聚合 分組、F Q)
聚合
aggregate()是QuerySet的一個終止子句,也就是說,他返回一個包含一些鍵值對的字典,在它的后面不可以再進行點(.)操作.
鍵的名稱是聚合值的標識符,只是計算出來的聚合值.鍵的名稱是按照字段和聚合函數的名稱自動生成出來的.
聚合函數的導入
from django.db.models import Max, Min, Sum, Avg, Count
簡單使用示例:
查詢所有書的平均價格.
1 from django.db.models import Avg, Sum, Max, Min, Count 2 3 ret = models.Book.objects.all().aggregate(Avg("price")) 4 5 >>> {'price__avg': 13.233333} # price__avg 是自動成出來的,前邊是聚合的字段,后邊是聚合函數的名稱.
當需要為聚合值指定一個名稱,可以向聚合子句提供它.
from django.db.models import Avg, Sum, Max, Min, Count models.Book.objects.aggregate(average_price=Avg('price')) # average_price 為自己指定的名稱.
>>> {'average_price': 13.233333}
當需要生成不止一個聚合時,可以向aggregate()子句中添加另一個參數.
查詢所有圖書價格的平均值 最大值 最小值.
1 from django.db.models import Avg, Sum, Max, Min, Count 2 3 models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price")) # 4 5 >>> {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}
查詢所有圖書中最高的價格和平均價格
1 from django.db.models import Max, Avg 2 3 ret = models.Book.objects.aggregate(Max('price'), avg=Avg('price')) #
分組
現有員工表如下:
需求:
按照部門分組求平均工資
ORM操作如下:
1 from django.db.models import Avg 2 3 models.Employee.objects.values("dept").annotate(avg=Avg("salary").values("dept", "avg") #
按照哪個字段分組,就將哪個字段寫在objects后面的values中.
注意:
分組使用的是annotate(),他不是一個終止子句,他的后邊可以跟其他操作.
連表查詢:
表格如下:
按照部門分組求平均工資:
1 from django.db.models import Avg 2 3 models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg") #
按照部門分組,就從部門表上開始查,聚合函數Avg()中寫需要差的字段,按照雙下划線的方法找到字段.
其他示例:
統計每一本書的作者的數量
1 from app01 import models 2 from django.db.models import Count 3 4 ret = models.Book.objects.annotate(Count('author')).values() #
查詢每個出版社出版的圖書中價格最低的
方式一:
1 from app01 import models 2 from django.db.models import Min 3 4 ret = models.Publisher.objects.annotate(Min('book__price')).values() #
從出版社表查,聚合函數Min()中寫需要查詢的字段,使用雙下滑線(__)的方法查詢到需要的字段.
方式二:
1 from app01 import models 2 from django.db.models import Min 3 4 ret = models.Book.objects.values('publisher__name').annotate(min=Min('price')) #
從書表中查,objects后面的values()中寫分組依據的字段名.然后跟annotate()中寫聚合函數,聚合函數中寫查詢的字段.
查詢作者大於1的圖書
1 from app01 import models 2 from django.db.models import Count 3 4 ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1).values() #
從書表中查詢,先統計每一本書的作者的數量,然后使用filter()過濾出符合條件的對象.
查詢每位作者所出書的總價格
1 from app01 import models 2 from django.db.models import Sum 3 4 ret = models.Author.objects.annotate(Sum('books__price')).values() #
從作者表查詢,聚合函數Sum()中填寫查詢的字段
F
在此之前我們構造的過濾器都只是將字段與某個常量作比較,如果將兩個字段做比較時,可以使用F().F()的實例可以再查詢中引用字段,來比較同一個model實例(對象)中的兩個不同字段的值.
簡單點說就是可以用來動態數據對比查詢.
F的導入
from django.db.models import F
查詢銷量大於庫存的圖書
from django.db.models import F ret = models.Book.objects.filter(sale__gt=F('kucun')).values() #
F的用法是F('字段名'),F()是用來取值的.
將所有書的銷量更新為原來的2倍.
1 from app01 import models 2 from django.db.models import F 3 4 ret = models.Book.objects.all().update(sale=F('sale') * 2) #
可以進行翻倍操作.
PS:
知識補充 ---> .update() 更新
僅對選中的QuerySet對象進行更新,速度快.
1 from app01 import models 2 3 ret = models.Book.objects.filter(id=2).update(sale=100) #
將id為2的書的銷量設置為100.
將所有書的銷量更新為原來的2倍.
1 from app01 import models
2 from django.db.models import F 3 4 ret = models.Book.objects.all().update(sale=F('sale') * 2) #
可以進行翻倍操作.
知識補充 ---> .save() 修改后進行保存.
對所有對象都進行保存,操作數據量大,速度慢.
1 from app01 import models 2 3 obj = models.Book.objects.get(id=2) 4 obj.sale='1000' 5 obj.save()
將id為2的書的銷量設置為1000.
Q
filter()等方法中的關鍵字參數查詢都是一起進行'and'的,如果需要進行更加復雜的查詢,可以使用Q對象.
示例:
查詢id小於等於3或者id大於等於6的書
1 from app01 import models 2 from django.db.models import Q 3 4 ret = models.Book.objects.filter(Q(id__lte=3) | Q(id__gte=6)) #
Q()寫在filter()中,使用或(or)查詢是每個Q()使用管道符(|)連接,管道符表示或(or)的關系.
查詢id大於等於10並且銷量大於等於3000的書.
1 from app01 import models 2 from django.db.models import Q 3 4 ret = models.Book.objects.filter(~Q(price__gte=10) & Q(sale__gte=3000)).values() #
使用&連接時表示and.