聚合,咱們應該有這個概念,由於在數據庫的SQL語言裏面有聚合函數的概念,聚合,字面意思來講,就是把一類東西放在一塊兒,可是跟分組又不太同樣.python
咱們知道咱們在寫SQL語句的時候,分組groupby和聚合函數是分不開的,由於一旦select語句裏面有分組,那麼咱們就只能查詢到分組依據的字段以及一些聚合函數組成的字段,別的字段寫在select後面會報錯的.git
因此,既然ORM是用來操做數據庫的,那麼咱們在使用聚合查詢的時候,就要遵循這個規律.聚合查詢的具體用法以下:數據庫
# 首先導入聚合函數,聚合函數的關鍵字爲aggregate from django.db.models import Max,Min,Sum,Count,Avg # 大概格式爲:models.表名.objects.查詢方式(匹配條件).aggregate(聚合函數(表中的字段)) res = models.Book.objects.all().aggregate(Avg('price')) print(res)
分組查詢的關鍵字爲annotate,使用起來很是的簡單,實際在數據庫裏的操做其實就是groupby,分組查詢會按照models後面的表名來分組,而後在後面括號內對分組後的數據進行操做django
# 分組查詢的格式爲:models.表名.objects.annotate(對組內數據作操做) res = models.Book.objects.annotate(author_number=Count('authors').values('author_num')) print(res)
上面的聚合和分組查詢都是咱們從表中取出字段,而後與一個咱們設定好的常量做比較,設想這樣一種情景,若是咱們須要從數據庫取出來兩個不一樣字段的值做比較,該如何實現呢?Django裏面就給咱們提供了F和Q查詢來解決這一問題.後端
from django.db.models import F,Q res = models.Book.objects.filter(sell = F('kucun')) print(res) # 以上語句能夠實如今Book表中,咱們以kucun列爲依據,來查詢獲得本身想要的數據,甚至能夠在查詢的時候直接對數據作操做,好比 res = models.Book.objects.filter(sell = F('kucun')+100) print(res) # 而Q查詢比F查詢更增強大,好比如下情景 # 咱們須要根據不止一個條件來篩選記錄,並且這些條件並非and關係,而是or,或者not,此時就可使用Q查詢來解決問題,好比: res = models.Book.objects.filter(Q(title='python')|Q(kucun=666)) res1 = models.Book.objects.filter(~Q(title='python')|Q(kucun=666)) print(res,res1) # 以上兩個例子,在兩個Q之間用|是or的意思,即二者只要有一個成立就算符合條件,~則是取反的意思
Q查詢還有一種更優秀的用法,咱們知道Q查詢實際上是一個類,因此咱們經過實例化產生一個對象,而後經過操做這個對象來實現Q查詢以及對數據進行篩選的目的,好比數組
from django.db.models import Q q = Q() q.connector = 'or' # 這裏能夠直接配置其查詢的方式,能夠是or,能夠是not q.children.append(('title','python')) q.children.append(('kucun',666)) res = models.Book.objects.filter(q) print(res)
ORM的查詢優化通常會有四個比較經常使用的方法,他們都是成對出現,對比使用的,即only和defer,select_relater和prefetch_related,下面咱們逐一介紹.緩存
only和defer('字段') 首先他們的用法都是在關鍵字後面括號中加入表中有的字段. only會將括號內字段對應的全部數據直接封裝起來,而後返回給咱們的對象中,由於only()最後返回的是一個對象,而後咱們對這個對象來進行操做的時候,若是點出來的是以前括號內的字段,那麼這次查詢就不會再通過數據庫,可是若是點出來是括號內不包含的字段,那麼每次都會從新查詢數據庫. 作一個類比來講,only後面括號內字段所對應的數據至關因而拿出來放在了計算機的緩存中,咱們在查詢這個字段的時候就直接從緩存裏取,而不須要再去查詢數據庫,能夠節約大量查詢的時間,固然這只是一個類比,實際狀況並非緩存的概念. defer的用法就和only徹底相反,defer後面括號內字段對應的數據,在每次查詢的時候都須要查詢數據庫,而括號內不包含的字段對應的數據查詢則不須要查詢數據庫. 我的理解only和defer的用法,only應該是用在不常修改的字段,也就是說only後面括號內的字段應該是修改次數儘可能少的字段,這樣既能提高效率,查詢出來又不會出錯.同理,defer後面括號內則是應該寫頻繁修改的字段,須要實時監控其變化的那種字段,比較合適.
select_relater和prefetch_related('外鍵關聯表的表名') 首先,select_relater和prefetch_related的共同點在於其傳參的規則是相同的,其後面的括號裏面都只能放外鍵字段,且只能放一對一和一對多的外鍵字段,不能放多對多的字段,並且能夠疊加,便可以select_related(外鍵字段__外鍵字段__外鍵字段)這樣放. select_related會自動幫咱們作連表操做,這些表必須是有外鍵相關聯的,select_related將連表以後的數據所有查詢出來,而後封裝起來,傳給對象. 而prefetch_related看似也是一個連表操做,其實不是,prefetch_related其實是一種相似子查詢的存在,其會屢次查詢不一樣的表,而後把最後的結果返回出來. 這兩種方法的區別在於 第一種,內部自動連表,消耗的資源和時間都在連表上,對數據庫的操做比較少,數據庫壓力小 第二種,內部不作連表,消耗的資源和時間都在對數據庫的查詢上,數據庫壓力較大,可是總體效率較高
ORM中的字段就是咱們在models.py裏面定義表類型的時候,對於字段的定義所用的格式,經常使用的有如下幾種:markdown
# 自增的數字,經常使用來設置主鍵,primary_key = True就爲主鍵 AutoField(primary_key = True) # 最經常使用的字符類型,至關於python中的varchar,max_length爲其最大長度,超過這個長度的會被捨棄 CharField(max_length=32) # 整型,默認括號內爲空 IntegerField() # 時間格式,經常使用參數有兩個: DateField() auto_now:每次對對象進行操做都會更新當前時間 auto_now_add:在建立或添加對象的時候會添加這個時間,而後不會改變 # 小數格式的數字,max_digits爲數字的總位數,decimal_places爲數字的小數的位數 DecimalField(max_digits=8,decimal_places=2) # 布爾類型,存儲到數據庫中的時候是0/1,並非True和False BooleanField()
choices參數一般是IntegerField中的參數,由於咱們市場但願的是用簡單的數字來代替不一樣的意思,或者選項,好比咱們在定義一個類中字段的是時候,該字段要顯示用戶的性別,咱們能夠這麼寫:app
# models.py choices = ( (1,'male'), (2,'female'), (3,'guess') ) sex = models.IntegerField(choices=choices) # 以上這種操做就能夠實現咱們的需求,在後端向前端傳送數據的時候只須要傳1,2,3就能夠了,大大減小了傳送數據的量級
這種使用方式能夠簡化傳送數據的大小,可是在取數據的時候也和原來有些區別,並非直接用點的形式來取數據了.
from app01 import models user_obj = models.Userinfo.objects.filter(pk=1),first() res = user_obj.get_gender_display() print(res) # 其取值方式爲固定句式,即 # 數據對象.get_字段名_display() # 注意,若是數字沒有對應關係的話,該種方式取出來的仍是這個數字,並不會報錯
咱們知道數據庫中有事務,事務的四大特色ACID爲
原子性
一致性
隔離性
持久性
因此咱們在ORM中也須要有事務的存在.具體操做以下
from django.db import transaction with transaction.atomic() #這裏寫的全部ORM語句都屬於同一個事務 # 事務的結束標誌就是這一個縮進