第七章、模型詳解 -- 查詢函數

添加測試數據

  • 在SQLyog中執行

 

INSERT INTO app_bookinfo(title,bpub_date,bread,bcomment,isDelete) VALUES
('三國演義','1980-5-1',12,34,0),
('紅樓夢','1986-7-24',36,40,0),
('水滸傳','1995-12-24',20,80,0),
('西遊記','1987-11-11',58,24,0);

 

INSERT INTO app_personinfo(pname,pgender,pcomment,isDelete) VALUES
('曹操',1,'字孟德',0),
('劉備',1,'字玄德',0),
('諸葛亮',1,'字孔明',0),
('孫權',1,'字仲謀',0),
('賈寶玉',1,'榮國府公子',0),
('林黛玉',0,'金陵十二釵之冠',0),
('薛寶釵',0,'薛姨媽之女',0),
('王熙鳳',0,'賈璉之妻',0),
('賈母',0,'寶玉祖母',0),
('宋江',1,'呼保義',0),
('盧俊義',1,'玉麒麟',0),
('吳用',1,'智多星',0),
('公孫勝',1,'入雲龍',0),
('孫悟空',1,'唐僧的大徒弟',0),
('唐僧',1,'玄奘',0),
('豬八戒',1,'悟能',0),
('沙僧',1,'沙悟淨',0);

配置mysql數據庫日誌

通過日誌文件可以查看對數據庫的操作記錄,mysql默認不產生日誌文件,需要進行配置:

  • 手動開啓日誌
    進入mysql命令行:mysql -u root -p
    查詢日誌狀態:show variables like 'general_log%';
    開啓日誌:set global general_log = 'on';

  • 自動開啓日誌
    打開mysql配置文件my.ini,路徑是C:\ProgramData\MySQL\MySQL Server 8.0
    general-log的值修改爲1

     

  • 重啓mysql服務

  • 下載、安裝baretail.exe工具

  • baretail.exe中打開日誌文件,
    文件位置:C:\ProgramData\MySQL\MySQL Server 8.0\Data

  • 在linux中使用tail -f 日誌文件,監控日誌的變化

查詢函數

通過模型類.objects屬性可以調用如下函數,實現對模型類對應的數據表的查詢。

函數名 功能 返回值 說明
get 返回表中滿足條件的一條數據,並且只能是一條數據 模型類對象 參數中寫查詢條件。
1) 查到多條數據拋異常
MultipleObjectsReturned
2) 查詢不到數據拋異常
DoesNotExist
all 返回表格中所有數據 QuerySet類型 查詢集
filter 返回滿足條件的數據 QuerySet類型 參數寫查詢條件
exclude 返回不滿足條件的數據 QuerySet類型 參數寫查詢條件
order_by 對查詢結果進行排序 QuerySet類型 參數中寫根據哪些字段進行排序

說明:
all函數以‘查詢集’的形式返回所有數據表中的記錄,該操作不會立限執行
只有使用了查詢集中的數據時纔會執行查詢

實例演練

  • get函數示例:查詢圖書id爲3的圖書信息

 

def index(request):
    list = BookInfo.objects.get(id=3)
    print(list.id, list.btitle, list.bpub_date, list.bread, list.bcomment)
    return render(request, 'app/index.html')

  • all函數示例:查詢圖書所有信息

 

def index(request):
    list = BookInfo.objects.all()
    for book in list:
        print(book.id, book.btitle, book.bpub_date, book.bread, book.bcomment)
    return render(request, 'app/index.html')

條件查詢

在Django中,通過調用過濾器filter()exclude()get()等實現SQL中的where子句

語法格式: 屬性名稱__比較運算符 = 值

說明:

  • 屬性名稱和比較運算符間使用 兩個下劃線
  • 通過"屬性名_id"表示外鍵對應對象的id值。

條件運算符

修改views.py文件,在index視圖中編寫如下查詢代碼:

  • 等值查詢
    exact:表示判等

 

例:查詢編號爲1的圖書
list=BookInfo.objects.filter(id__exact=1)
可簡寫爲:
list=BookInfo.objects.filter(id=1)

 

def index(request):
    list = BookInfo.objects.filter(id__exact=1)

    for book in list:
        print(book.btitle, book.bpub_date)

    return render(request, 'app/index.html')
  • 模糊查詢
    contains:是否包含

說明:如果要包含%無需轉義,直接寫即可。

 

例:查詢書名包含'傳'的圖書
list = BookInfo.objects.filter(btitle__contains='傳')

startswith、endswith:以指定值開頭或結尾。

 

例:查詢書名以'夢'結尾的圖書
list = BookInfo.objects.filter(btitle__endswith='夢')

以上運算符都區分大小寫,在這些運算符前加上i表示不區分大小寫,如iexact、icontains、istartswith、iendswith.

  • 空查詢
    isnull:是否爲null。

 

例:查詢書名不爲空的圖書。
list = BookInfo.objects.filter(btitle__isnull=False)
  • 範圍查詢
    in:是否包含在範圍內。

 

例:查詢編號爲1或3或5的圖書
list = BookInfo.objects.filter(id__in=[1, 3, 5])
  • 比較查詢
    gt、gte、lt、lte:大於、大於等於、小於、小於等於。

注意:參數中不能使用等號之外的比較符號
BookInfo.objects.filter(id > 3) 這種寫法是錯誤的

 

例:查詢編號大於3的圖書
list = BookInfo.objects.filter(id__gt=3)

不等於的運算符,使用exclude()過濾器。

 

例:查詢編號不等於3的圖書
list = BookInfo.objects.exclude(id=3)
  • 日期查詢
    year、month、day、week_day、hour、minute、second:對日期時間類型的屬性進行運算。

 

例:查詢1980年發表的圖書。
list = BookInfo.objects.filter(bpub_date__year=1980)

 

例:查詢1980年1月1日後發表的圖書。
list = BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))
  • F對象
    之前的查詢都是屬性與常量值比較,如果是兩個屬性比較,可以通過F對象進行
    F對象被定義在django.db.models

語法格式:F(屬性名)

 

例:查詢閱讀量大於等於評論量的圖書。
from django.db.models import F
list = BookInfo.objects.filter(bread__gte=F('bcomment'))

可以在F對象上使用算數運算。

 

例:查詢閱讀量大於2倍評論量的圖書
list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
  • Q對象
    多個過濾器逐個調用表示邏輯與關係,相當於where子句的AND關鍵字。

 

例:查詢閱讀量大於20,並且編號小於3的圖書。
list=BookInfo.objects.filter(bread__gt=20,id__lt=3)
或
list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)

如果需要實現邏輯或(OR)查詢,需要使用Q()對象結合 | 運算符,
Q對象被義在django.db.models中。

語法格式:Q( 屬性名__運算符 = 值 )

 

例:查詢閱讀量大於20的圖書,改寫爲Q對象如下。
from django.db.models import Q
list = BookInfo.objects.filter(Q(bread__gt=20))

Q對象可以使用&、|連接,&表示邏輯與,|表示邏輯或。

 

例:查詢閱讀量大於20,或編號小於3的圖書,只能使用Q對象實現
list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))

Q對象前可以使用~操作符,表示非not。

 

例:查詢編號不等於3的圖書。
list = BookInfo.objects.filter(~Q(pk=3))

聚合函數

使用aggregate()函數調用聚合函數。
聚合函數包括:AvgCountMaxMinSum,被定義在django.db.models

aggregate()返回一個字典類型,格式爲{' 屬性名小寫__聚合函數名小寫 ' :值},例如:{'bread__sum':3}

 

例:查詢圖書的總閱讀量。
from django.db.models import Sum
def index(request):
    s = BookInfo.objects.aggregate(Sum('bread'))
    print(s['bread__sum'])
    return render(request, 'app/index.html')

count函數返回一個數字,一般不使用aggregate()過濾器。

 

例:查詢圖書總數。
c = BookInfo.objects.count()

查詢集(QuerySet)

查詢集表示從數據庫中獲取的對象集合,在管理器上調用某些過濾器方法會返回查詢集,查詢集可以含有零個、一個或多個過濾器。過濾器基於所給的參數限制查詢的結果,從Sql的角度,查詢集和select語句等價,過濾器像where和limit子句。

返回查詢集的過濾器如下

  • all():返回所有數據。
  • filter():返回滿足條件的數據。
  • exclude():返回滿足條件之外的數據,相當於sql語句中where部分的not關鍵字。
  • order_by():對結果進行排序。

返回單個值的過濾器如下

  • get():返回單個滿足條件的對象
    • 如果未找到會引發"模型類.DoesNotExist"異常。
    • 如果多條被返回,會引發"模型類.MultipleObjectsReturned"異常。
  • count():返回當前查詢結果的總條數。
  • aggregate():聚合,返回一個字典。

判斷某一個查詢集中是否有數據

  • exists():判斷查詢集中是否有數據,如果有則返回True,沒有則返回False。

兩大特性

  • 惰性執行:創建查詢集不會訪問數據庫,直到調用數據時,纔會訪問數據庫,調用數據的情況包括迭代、序列化、與if合用。
  • 緩存:使用同一個查詢集,第一次使用時會發生數據庫的查詢,然後把結果緩存下來,再次使用這個查詢集時會使用緩存的數據。

示例:查詢所有,編輯booktest/views.py的index視圖,運行查看。

 

list=BookInfo.objects.all()

查詢集的緩存

每個查詢集都包含一個緩存來最小化對數據庫的訪問。

在新建的查詢集中,緩存爲空,首次對查詢集求值時,會發生數據庫查詢,django會將查詢的結果存在查詢集的緩存中,並返回請求的結果,接下來對查詢集求值將重用緩存中的結果。

  • 如下是兩個查詢集,無法重用緩存,每次查詢都會與數據庫進行一次交互,產生2條SQL語句,增加了數據庫的負載。

 

from booktest.models import BookInfo
[book.id for book in BookInfo.objects.all()]
[book.id for book in BookInfo.objects.all()]

  • 經過存儲後,可以重用查詢集,只產生1條SQL語句,第二次使用緩存中的數據。

 

list=BookInfo.objects.all()
[book.id for book in list]
[book.id for book in list]

限制查詢集 (LIMIT子句)

可以對查詢集進行取下標或切片操作,等同於sql中的limit和offset子句,對查詢集進行切片後返回一個新的查詢集,不會立即執行查詢

注意:不支持負數索引。

獲取一個對象,直接使用[0],等同於[0:1].get(),
[0]如果沒有數據,引發IndexError異常,
[0:1].get()如果沒有數據,引發DoesNotExist異常。

示例:獲取第1、2項,運行查看。

 

list=BookInfo.objects.all()[0:2]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章