Django學(xué)習(xí)筆記:F對象、Q對象、聚合分組查詢和原生SQL
F對象? ?
在高并發(fā)的情景下,若要對一個文章的點贊量進行增量更新,我們就不可以再程序里先讀后寫了,因為多個線程在短時間內(nèi)讀到的可能是同一時刻的數(shù)據(jù),在程序中做增量更新后保存到數(shù)據(jù)庫可能會導(dǎo)致重復(fù)覆蓋,解決方法有兩個:在java中我習(xí)慣用鎖機制和事務(wù)來控制。也可以直接寫成mysql語句,在一條語句中做更新操作,這得益于mysql自己內(nèi)部的鎖機制可以對線程的數(shù)據(jù)更新加鎖。
? ?了解到這一點后,我們可以在django中也采用類似的機制來實現(xiàn),由于django的orm機制本質(zhì)上是對mysql語法的進一步封裝,想要達到加鎖的效果就直接利用mysql的鎖即可。這里我們需要用到F對象,F(xiàn)對象是對字段的抽象標(biāo)記。
記得先導(dǎo)入D對象再使用
? ? article.like=F('like')+1其實沒有在讀取數(shù)據(jù)也沒有再修改數(shù)據(jù),知識對字段做了一個提前的說明,直到執(zhí)行save(),框架就會自動生產(chǎn)sql語句:update article set like =like+1 where id =xxx 。利用的是mysql自帶的鎖,我們就不必在業(yè)務(wù)層加鎖了。
? ? F屬性是對字段的抽象標(biāo)記,很多情況下都可以來簡化代碼的書寫:如果我們要選出收藏量大于點贊數(shù)的文章的列表:
? 相當(dāng)于sql中的:select * from artice where collect >like。
? Q對象
?Q對象是用來實現(xiàn)或、非條件的對象,在django中,條件并列傳入框架中默認為&關(guān)系,也就是“并且”的關(guān)系。要實現(xiàn)|以及~則需要再引進Q對象,當(dāng)然Q對象也可以實現(xiàn)“且”的作用
? Q(cdt1)|Q(cdt2) :條件一或者條件二名字
? Q(cdt1)&Q(cdt2): 條件一和條件二同時滿足
? Q(cdt1)&~Q(cdt2):條件一滿足并且條件二不滿足
? ~Q(cdt1)&~Q(cdt2) :條件一和條件二都不滿足
Q對象的位置和F對象同級:
用途如下:

聚合查詢
整表聚合:

整表聚合返回的是字典,這種返回形式更加自由

分組聚合:


這里一開始不好理解,通過簡單的代碼來習(xí)慣這種用法:

? ? values('c1',?'c2'...)獲取表的每一行數(shù)據(jù)的內(nèi)容,每一行數(shù)據(jù)的表示以下格式:
{c1:c1val,c2:c2val,...}。
? ? 獲取到指定字段到所有數(shù)據(jù)后,就可以利用annotate對數(shù)據(jù)根據(jù)指定的字段進行分組,以聚合函數(shù)返回值作為該組的值。可以表示為以下格式:
{c1:c1val,c2:c2val,...,名:聚合函數(shù)(作用字段),...}? 分組體現(xiàn)在對于合并了相同的cn:cnval。而聚合函數(shù)得到的鍵值對,類似于對該組的追加的注解,所以分組聚合的函數(shù)叫做annotate,某種程度來看挺合理的。

? 在寫orm的內(nèi)容的時候,我覺得單表簡單查詢上orm很有意義,但是在復(fù)雜查詢的時候,可能是sql更有優(yōu)勢了,對此,django也允許直接使用sql來與數(shù)據(jù)庫交互。

??注意,拼接參數(shù)層面已經(jīng)包含sql注入的檢查了。
多表查詢方面,這個文章說的不錯!