Django 聚合分組F與Q查詢及choices
一、聚合查詢
需要導入模組:from django.db.models import Max, Min, Sum, Count, Avg
關鍵語法:aggregate(聚合結果別名 = 聚合函數(參數))
查詢結果:使用聚合函數,從每一個組中獲取結果:字典
注意點:
1 聚合函數必須在分組之後才能使用
2 沒有分組,即默認整體就是一組
3 查詢結果為 普通字典
"""
聚合查詢通常情況下都是配合分組一起使用的
只要是跟資料庫相關的模組
基本上都在 django.db.models 裡面
上述沒有那麼應該在 django.db裡面
"""
from django.db.models import Max, Min, Sum, Count, Avg
# 1 所有書的平均價格
res = models.Book.objects.aggregate(Avg('price'))
print(res)
# 2 上述方法一次性使用
res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Count('pk'), Avg('price'))
print(res)
二、分組查詢
1 關鍵字:annotate
2 默認以當前表 id 分組,並使用聚合函數在組內進行聚合計算,得到結果作為查詢結果中組內的屬性
from django.db.models import Max, Min, Sum, Count, Avg
# 1 統計每一本書的作者個數
res = models.Book.objects.annotate() # models後面點什麼 就是按什麼分組
res1 = models.Book.objects.annotate(author_num = Count('authors')).values('title', 'author_num')
res2 = models.Book.objects.annotate(author_num = Count('authors__nid')).values('title', 'author_num')
print(res, res1, res3)
"""
author_num 自己定義的欄位 用來存儲統計出來的每本書對應的作者個數
"""
# 2 統計每個出版社賣的最便宜的書的價格
res = models.Publish.objects.annotate(min_price = Min('book__price')).values('name', 'min_price')
print(res)
# 3 統計不止一個作者的圖書
# 先按照圖書分組 求每一本書對應的作者個數
# 過濾出不止一個作者的圖書
res = models.Book.objects.annotate(author_num = Count('authors')).filter(author_num__gt = 1).values('title', 'author_num')
print(res)
# 4 查詢每個作者出的書的總價格
res = models.Author.objects.annotate(sum_price = Sum('book__price')).values('name', 'sum_price')
print(res)
# 5 統計 price大於150元 的書籍的作者個數
res = models.Book.objects.filter(price__gt = 150).annotate(num_authors = Count('authors')).values('title', 'num_authors')
print(res)
三、F與Q查詢
# F查詢
"""
能夠幫助你直接獲取到表中某個欄位對應的數據
"""
from django.db.models import F
# 1 將所有書籍的價格提升 10 塊
models.Book.objects.update(price = F('price') + 10)
# 2 將 django 書的名稱後面加上 ' web' 字
"""
在操作字元類型的數據的時候 F不能夠直接做到字元串的拼接
"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.filter(title = "django").update(title = Concat(F('title'), Value(' web')))
# Q查詢
"""
filter括弧內多個參數是and關係
"""
from django.db.models import Q
# Q包裹逗號分割 還是and關係
res1 = models.Book.objects.filter(Q(price__lt = 300), Q(price__gt = 400))
print(res1)
# | or關係
res2 = models.Book.objects.filter(Q(pub_date__lt = '2020-01-01') | Q(price__gt = 300))
print(res2)
# ~ not關係
res3 = models.Book.objects.filter( ~ Q(pub_date__lt = '2020-01-01') | Q(price__lt = 200))
print(res3) # <QuerySet []>
# Q的高階用法 能夠將查詢條件的左邊也變成字元串的形式
# 提前生成 Q 對象,並使用 append方法 添加條件
q = Q()
q.connector = 'or'
q.children.append(('pub_date__lt', '2020-01-01'))
q.children.append(('price__lt', 200))
res = models.Book.objects.filter(q) # 默認是and關係
print(res)
四、特殊參數choices
1 定義欄位時,指定參數 choices
2 choices 的值為元組套元組(事先定義好,一般在該表類中定義該欄位之前定義)
3 每一個元組存放兩個元素,形成一種對應關係
4 往資料庫中存值時,該欄位的值存為元組第一個元素即可
5 通過 對象.get_欄位名_display() 獲取對應的元組第二個元素值,當沒有對應關係時,返回的是它本身
示例:
# 定義一個 UserTest 表
class UserTest(models.Model):
name = models.CharField(max_length = 64)
gender_choices = ((1, '男'),(2, '女'),(3, '其他'))
gender = models.IntegerField(choices = gender_choices)
# 同步遷移到資料庫
python manage.py makemigrations
python manage.py migrate
# 在 test.py 配置測試環境
# 錄入數據
models.UserTest.objects.create(name = '小微', gender = 1)
models.UserTest.objects.create(name = '小芬', gender = 2)
models.UserTest.objects.create(name = '小桃', gender = 3)
models.UserTest.objects.create(name = '小月', gender = 4)
# 驗證choices
for user_obj in models.UserTest.objects.all():
print(user_obj.gender, end=' ')
print(user_obj.get_gender_display())
'''
1 男
2 女
3 其他
4 4
'''