# 模型查詢
## 簡介
* 查詢集表示從數據庫中獲取的對象集合
* 查詢集可以含有零個,一個或多個過濾器
* 過濾器基于所給的參數限制查詢的結果
* 從sql的角度,查詢集和select語句等價,過濾器像where和limit子句
* 知識點:
* 查詢集
* 字段查詢:比較運算符,F對象,Q對象
## 查詢集
* 在管理器上調用過濾器方法會返回查詢集
* 查詢集經過過濾器篩選后返回新的查詢集,因此可以寫成鏈式過濾
* 惰性執行:創建查詢集不會帶來任何數據庫的訪問,知道調用數據時,才會訪問數據庫
* 何時對查詢集求值:迭代、序列化、與if合用
* 何時對查詢集的方法,稱為過濾器
* all\(\)
* filter\(\)
* exclude\(\)
* order\_by\(\)
* values\(\):一個對象構成一個字典,然后構成一個列表返回
* 寫法:
\`\`\`
filter\(鍵1=值1,鍵2=值2\) 等價于 filter\(鍵1=值1\).filter\(鍵2=值2\)
```text
views:
def studentsearch(request):
studentsList = Students.stuObj.filter(sname="美")
return render(request,"myApp/students.html",{'students':studentsList})
urls:
url(r'^filter/$',views.studentsearch),
```
* 返回單個值的方法
* get\\(\\):返回單個滿足條件的對象
* 如果未找到會引發"模型類.DoesNotExist"異常
* 如果多條被返回,會引發"模型類.MultipleObjectsReturned"異常
* count\\(\\):返回當前查詢的總條數
* first\\(\\):返回第一個對象
* last\\(\\):返回最后一個對象
* exists\\(\\):判斷查詢集中是否有數據,如果有則返回True
## 限制查詢集
* \* 查詢集返回列表,可以使用下標的方式進行限制,等同于sql中的limit和offset子句
* \* 注意:不支持負數索引
* \* 使用下標后返回一個新的查詢集,不會立即執行查詢
* \* 如果獲取一個對象,直接使用\\[0\\],等同于\\[0:1\\].get\\(\\),可是如果沒有數據,\\[0\\]引發IndexError異常\\[0:1\\].get\\(\\)引發DoestNotExist異常
## 查詢集的緩存
* 每個查詢集都包含一個緩存來最小化對數據庫的方法
* 在新建的查詢集中,緩存為空,首次對查詢集求值時,會發生數據庫查詢,django會將查詢的結果存在查詢集的緩存中,并返回請求的結果,接下來對查詢機求值將重用緩存的結果
* 情況一:這構成了兩個查詢集,無法重用緩存,每次查詢都與數據庫進行一次交互,增加了數據庫的負載
print\(\[e.ename for e in Entry.objects.all\(\)\]\)
print\(\[e.ename for e in Entry.objects.all\(\)\]\)
```text
* 情況二:兩次循環使用同一個查詢集,第二次使用緩存中的數據
```
queryList = Entry.objects.all\(\)
print\(e.ename for e in queryList\)
print\(e.ename for e in queryList\)
* 何時查詢集不會被緩存:當只對查詢集的部分進行求值時會檢查緩存,但是如果這部分不在緩存中,那么接下來查詢返回的記錄將不會被緩存,這意味著使用索引來限制查詢集將不會填充緩存,如果這部分數據已經被緩存,則直接使用緩存中的數據
## 字段查詢
* \* 實現where子名,作為方法filter\\(\\)、exclude\\(\\)、get\\(\\)的參數
* \* 語法:屬性名稱\\_比較運算符 = 值
* \* 標識兩個下劃線,左側是屬性名稱,右側是比較類型
* \* 對于外鍵,使用"屬性名\\_id"表示外鍵的原始值
* \* 轉義:like語句中使用了%與,匹配數據中的%與,在過濾器中直接寫,例如:filter\\(name\\_\\_contains="%"\\) 等價于 where name like "%\%%",表示查找標題中的"%"
## 比較運算符
* exact:表示判等,大小寫敏感;如果沒有寫"比較運算符",表示判等
```text
filter(isDelete=False)
```
* contains:是否包含,大小寫敏感
```text
exclude(sname__contains="美")
```
* startswith、endswith:以value開頭或結尾,大小寫敏感
```text
exclue(sname__endswith="美")
```
* isnull、isnotnull:是否為null
```text
filter(sname__isnull = False)
```
* 在前面加個i表示區分大小寫,如iexact、icontains、istartswith、iendswith
* in:是否包飯在范圍內
```text
filter(ok__in = [1,2,3,4,5]
```
* gt、gte、lt、lte:大于、大于等于、小于、小于等于
```text
filter(id__gt = 3)
```
* year、month、day、week\\_day、hour、minute、second:對日期間類型的屬性進行運算
year、month、day、week\_day、hour、minute、second:對日期間類型的屬性進行運算
```text
filter(bpub_date__year=1980)
filter(bpub_date__gt=date(1980, 12, 31))
```
* 跨關聯關系的查詢:處理join查詢
* 語法:模型類名<屬性名><比較>
* 注:可以沒有\_\_<比較>部分,表示等于,結果同inner join
* 可返向使用,即在關聯的兩個模型中都可以使用
```text
filter(heroinfo_ _hcontent_ _contains='美')
```
* 查詢的快捷方式:pk,pk表示primary key,默認的主鍵是id
```text
filter(pk__lt=6)
```
### 聚合函數 {#聚合函數}
* 使用aggregate\(\)函數返回聚合函數的值
* 函數:Avg,Count,Max,Min,Sum
```text
from django.db.models import Max
maxAge = Students.stuObj.aggregate(Max('sname'))
print(maxAge)
```
* count的一般用法:
```text
count = list.count()
```
### F對象 {#f對象}
* 可以使用模型的字段A與字段B進行比較,如果A寫在了等號的左邊,則B出現在等號的右邊,需要通過F對象構造
```text
g = Grades.objects.filter(ggirlnum__lt=F('gboynum'))
```
* django支持對F\(\)對象使用算數運算
```text
g = Grades.objects.filter(ggirlnum__lt=F('gboynum')*2)
```
* F\(\)對象中還可以寫作“模型類\_\_列名”進行關聯查詢
```text
list.filter(isDelete=F('sgrade__isDelete'))
```
* 對于date/time字段,可與timedelta\(\)進行運算
```text
list.filter(a_date__lt=F('a_date') + timedelta(days=1))
```
### Q對象 {#q對象}
* 過濾器的方法中關鍵字參數查詢,會合并為And進行
* 需要進行or查詢,使用Q\(\)對象
* Q對象\(django.db.models.Q\)用于封裝一組關鍵字參數,這些關鍵字參數與“比較運算符”中的相同
```text
from django.db.models import Q
list.filter(Q(pk_ _lt=6))
```
* Q對象可以使用
&
(and)、\|(or)操作符組合起來
* 當操作符應用在兩個Q對象時,會產生一個新的Q對象
```text
list.filter(pk_ _lt=6).filter(sage__gt=10)
list.filter(Q(pk_ _lt=6) | Q(sage_ _gt=10))
```
* 使用~(not)操作符在Q對象前表示取反
```text
list.filter(~Q(pk__lt=6))
```
* 可以使用&\|~結合括號進行分組,構造做生意復雜的Q對象
* 過濾器函數可以傳遞一個或多個Q對象作為位置參數,如果有多個Q對象,這些參數的邏輯為and
* 過濾器函數可以混合使用Q對象和關鍵字參數,所有參數都將and在一起,Q對象必須位于關鍵字參數的前面
```text
view.py / filter
"""
# def studentsearch(request):
#過濾
# studentsList = Students.stuObj.filter(sname="美")
#contains
# studentsList = Students.stuObj.filter(sname__contains = "美")
#判等
# studentsList = Students.stuObj.filter(isDelete=False)
# exclude(排除)contains(包含)的內容
# studentsList = Students.stuObj.exclude(sname__contains="美")
#isnull,isnotnull:是否為null
# studentsList =Students.stuObj.filter(sname__isnull=False)
#startswith、endswith:以value開頭或結尾,大小寫敏感
# studentsList = Students.stuObj.exclude(sname__endswith="美")
#包含在范圍內
# studentsList = Students.stuObj.filter(pk__in = [1,3,6,10])
#gt、gte、lte、lt
#pk大于3
# studentsList = Students.stuObj.filter(id__gt = 3)
#過濾日期
# studentsList = Students.stuObj.filter(createTime_date__gt = 2016)
# 關聯_one
# studentsList = Students.stuObj.filter(sgrade__gname="python01")
# 聚合函數
#Max()函數
# maxAge = Students.stuObj.aggregate(Max('sname'))
# print(maxAge)
# F對象
# g = Grades.objects.filter(ggirlnum__lt=F('gboynum')*2)
# print(g)
# return render(request,"myApp/students.html",{'students':studentsList})
"""
```