2 Model層 - 模型查詢


2 Model層 - 模型查詢

 

 

1.簡介

  • 查詢集表示從數據庫中獲取的對象集合
  • 查詢集可以含有零個、一個或多個過濾器
  • 過濾器基於所給的參數限制查詢的結果
  • 從Sql的角度,查詢集和select語句等價,過濾器像where和limit子句
  • 接下來主要討論如下知識點
    • 查詢集
    • 字段查詢:比較運算符,F對象,Q對象

 

2.查詢集

  • 在管理器上調用過濾器方法會返回查詢集
  • 查詢集經過過濾器篩選后返回新的查詢集,因此可以寫成鏈式過濾
  • 惰性執行:創建查詢集不會帶來任何數據庫的訪問,直到調用數據時,才會訪問數據庫
  • 何時對查詢集求值:迭代,序列化,與if合用
  • 返回查詢集的方法,稱為過濾器
all()
filter()
exclude()
order_by()
values():一個對象構成一個字典,然后構成一個列表返回

 

 

 

復制代碼
>>> BookInfo.books2.values()
[{'bcommet': 34L, 'btitle': u'\u5c04\u96d5\u82f1\u96c4\u4f20', 'bpub_date': datetime.datetime(1980, 5, 1, 0, 0, tzinfo=<UTC>), 'isDelete': False, u'id': 1L, 'bread': 12L}, {'bcommet': 40L, 'btitle': u'\u5929\u9f99\u516b\u90e8', 'bpub_date': datetime.datetime(1986, 7, 24, 0, 0, tzinfo=<UTC>), 'isDelete': False, u'id': 2L, 'bread': 36L}, {'bcommet': 80L, 'btitle': u'\u7b11\u50b2\u6c5f\u6e56', 'bpub_date': datetime.datetime(1995, 12, 24, 0, 0, tzinfo=<UTC>), 'isDelete': False, u'id': 3L, 'bread': 20L}, {'bcommet': 24L, 'btitle': u'\u96ea\u5c71\u98de\u72d0', 'bpub_date': datetime.datetime(1987, 11, 11, 0, 0, tzinfo=<UTC>), 'isDelete': False, u'id': 4L, 'bread': 58L}, {'bcommet': 0L, 'btitle': u'abc', 'bpub_date': datetime.datetime(1990, 1, 1, 0, 0, tzinfo=<UTC>), 'isDelete': False, u'id': 5L, 'bread': 0L}]
>>>
復制代碼

 

 

  • 返回單個值的方法
復制代碼
get():返回單個滿足條件的對象
如果未找到會引發"模型類.DoesNotExist"異常
如果多條被返回,會引發"模型類.MultipleObjectsReturned"異常
count():返回當前查詢的總條數
first():返回第一個對象
last():返回最后一個對象
exists():判斷查詢集中是否有數據,如果有則返回True
復制代碼

 

 

限制查詢集

  • 查詢集返回列表,可以使用下標的方式進行限制,等同於sql中的limit和offset子句
  • 注意:不支持負數索引
  • 使用下標后返回一個新的查詢集,不會立即執行查詢
  • 如果獲取一個對象,直接使用[0],等同於[0:1].get(),但是如果沒有數據,[0]引發IndexError異常,[0:1].get()引發DoesNotExist異常

查詢集的緩存

  • 每個查詢集都包含一個緩存來最小化對數據庫的訪問
  • 在新建的查詢集中,緩存為空,首次對查詢集求值時,會發生數據庫查詢,django會將查詢的結果存在查詢集的緩存中,並返回請求的結果,接下來對查詢集求值將重用緩存的結果
  • 情況一:這構成了兩個查詢集,無法重用緩存,每次查詢都會與數據庫進行一次交互,增加了數據庫的負載
print([e.title for e in Entry.objects.all()])
print([e.title for e in Entry.objects.all()])

 

  • 情況二:兩次循環使用同一個查詢集,第二次使用緩存中的數據
querylist=Entry.objects.all()
print([e.title for e in querylist])
print([e.title for e in querylist])

 

  • 何時查詢集不會被緩存:當只對查詢集的部分進行求值時會檢查緩存,但是如果這部分不在緩存中,那么接下來查詢返回的記錄將不會被緩存,這意味着使用索引來限制查詢集將不會填充緩存,如果這部分數據已經被緩存,則直接使用緩存中的數據

 

 

3.字段查詢

  • 實現where子名,作為方法filter()、exclude()、get()的參數
  • 語法:屬性名稱__比較運算符=值
  • 表示兩個下划線,左側是屬性名稱,右側是比較類型
  • 對於外鍵,使用“屬性名_id”表示外鍵的原始值
  • 轉義:like語句中使用了%與,匹配數據中的%與,在過濾器中直接寫,例如:filter(title__contains="%")=>where title like '%\%%',表示查找標題中包含%的

比較運算符

  • exact:表示判等,大小寫敏感;如果沒有寫“ 比較運算符”,表示判等
filter(isDelete=False)

    

 

  • contains:是否包含,大小寫敏感
exclude(btitle__contains='傳')

 

 

  • startswith、endswith:以value開頭或結尾,大小寫敏感
exclude(btitle__endswith='傳')

 

  • isnull、isnotnull:是否為null
filter(btitle__isnull=False)

 

  • 在前面加個i表示不區分大小寫,如iexact、icontains、istarswith、iendswith
  • in:是否包含在范圍內
filter(pk__in=[1, 2, 3, 4, 5])

 

 

  • gt、gte、lt、lte:大於、大於等於、小於、小於等於
filter(id__gt=3)

 

  • year、month、day、week_day、hour、minute、second:對日期間類型的屬性進行運算
filter(bpub_date__year=1980)
filter(bpub_date__gt=date(1980, 12, 31))

 

 

  • 跨關聯關系的查詢:處理join查詢
    • 語法:模型類名 <屬性名> <比較>
    • 注:可以沒有__<比較>部分,表示等於,結果同inner join
    • 可返向使用,即在關聯的兩個模型中都可以使用
filter(heroinfo_ _hcontent_ _contains='八')

 

 

 

  • 查詢的快捷方式:pk,pk表示primary key,默認的主鍵是id
filter(pk__lt=6)

 

 

 

 

 

聚合函數

  • 使用aggregate()函數返回聚合函數的值
  • 函數:Avg,Count,Max,Min,Sum
from django.db.models import Max
maxDate = list.aggregate(Max('bpub_date'))

 

 

  • count的一般用法:
count = list.count()

 

 

 

 

 

 

F對象

  • 可以使用模型的字段A與字段B進行比較,如果A寫在了等號的左邊,則B出現在等號的右邊,需要通過F對象構造
list.filter(bread__gte=F('bcommet'))

 

 

 

 

  • django支持對F()對象使用算數運算
list.filter(bread__gte=F('bcommet') * 2)

 

  • F()對象中還可以寫作“模型類__列名”進行關聯查詢
list.filter(isDelete=F('heroinfo__isDelete'))

 

  • 對於date/time字段,可與timedelta()進行運算
list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))

 

Q對象:邏輯或,邏輯與

邏輯與

 

 

  • 過濾器的方法中關鍵字參數查詢,會合並為And進行
  • 需要進行or查詢,使用Q()對象
  • Q對象(django.db.models.Q)用於封裝一組關鍵字參數,這些關鍵字參數與“比較運算符”中的相同
from django.db.models import Q
list.filter(Q(pk_ _lt=6))

 

  • Q對象可以使用&(and)、|(or)操作符組合起來
  • 當操作符應用在兩個Q對象時,會產生一個新的Q對象
list.filter(pk_ _lt=6).filter(bcommet_ _gt=10)
list.filter(Q(pk_ _lt=6) | Q(bcommet_ _gt=10))

 

 

  • 使用~(not)操作符在Q對象前表示取反
list.filter(~Q(pk__lt=6))

 

  • 可以使用&|~結合括號進行分組,構造做生意復雜的Q對象
  • 過濾器函數可以傳遞一個或多個Q對象作為位置參數,如果有多個Q對象,這些參數的邏輯為and
  • 過濾器函數可以混合使用Q對象和關鍵字參數,所有參數都將and在一起,Q對象必須位於關鍵字參數的前面

 

 

4 自連接

  • 對於地區信息,屬於一對多關系,使用一張表,存儲所有的信息
  • 類似的表結構還應用於分類信息,可以實現無限級分類
  • 新建模型AreaInfo,生成遷移
class AreaInfo(models.Model):
atitle = models.CharField(max_length=20)
aParent = models.ForeignKey('self', null=True, blank=True)
  • 訪問關聯對象
上級對象:area.aParent
下級對象:area.areainfo_set.all()
  • 加入測試數據(在workbench中,參見“省市區mysql.txt”)
  • 在booktest/views.py中定義視圖area
from models import AreaInfo
def area(request):
area = AreaInfo.objects.get(pk=130100)
return render(request, 'booktest/area.html', {'area': area})
  • 定義模板area.html
<!DOCTYPE html>
<html>
<head>
<title>地區</title>
</head>
<body>
當前地區:{{area.atitle}}
<hr/>
上級地區:{{area.aParent.atitle}}
<hr/>
下級地區:
<ul>
{ %for a in area.areainfo_set.all%}
<li>{{a.atitle}}</li>
{ %endfor%}
</ul>
</body>
</html>
  • 在booktest/urls.py中配置一個新的urlconf
urlpatterns = [
url(r'^area/$', views.area, name='area')
]

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com