1. 程式人生 > >django之ORM查詢操作(二)

django之ORM查詢操作(二)

 

1.查詢集

  • 查詢集:表示從資料庫中獲取的模型物件集合
    • 管理器上呼叫過濾器方法會返回查詢集
    • 查詢集可以含有0個、一個或多個過濾器
  • 過濾器:基於所給的引數限制查詢的結果

1.1 返回列表的過濾器如下:

  • all():返回所有的資料(以物件形式)
  • filter():返回滿足條件的資料
  • exclude():返回滿足條件之外的資料,相當於sql語句中where部分的not關鍵字
  • order_by():返回排序後的資料

1.2 返回單個物件的過濾器如下:

  • get()
    :返回單個滿足條件的物件
    • 如果未找到會引發"模型類.DoesNotExist"異常
    • 如果多條被返回,會引發"模型類.MultipleObjectsReturned"異常
  • count():返回當前查詢的總條數
  • aggregate():聚合
  • exists():判斷查詢集中是否有資料,如果有則返回True,沒有則返回False

1.3 查詢集特點

  • 1.惰性執行:建立查詢集不會訪問資料庫,直到在模板中呼叫資料時,才會訪問資料庫
    • 呼叫資料的情況包括迭代、序列化、與if合用
  • 2.快取:查詢集的結果被存下來之後,再次查詢相同資料時會使用之前快取的資料

1.4 查詢集快取

  • 每個查詢集都包含一個快取來最小化對資料庫的訪問
  • 第一次查詢資料後,Django會將查詢集快取起來,並返回請求的結果
  • 再次查詢相同資料時將重用快取的結果

1.5限制查詢集

  • 查詢集返回列表,可以使用下標的方式進行限制,等同於sql中的limit和offset子句
  • 注意:不支援負數索引
  • 使用下標後返回一個新的查詢集,不會立即執行查詢
  • 如果獲取一個物件,直接使用[0],等同於[0:1].get()

    • 但是如果沒有資料,[0]引發IndexError異常,[0:1].get()引發DoesNotExist異常
  # User列表資訊檢視
def UserList(request):
  # 列表下標限制查詢集 :查詢第1,2項
  UserInfos = UserInfo.user.all()[0:2]

  # 構造上下文
  context = {'userlist':UserInfos}

  return render(request, 'user/userlist.html', context)

2.基礎條件查詢--針對一個屬性

查詢語法:模型屬性_條件運算子=值

  • 說明:查詢語句是屬性名稱和比較運算子間使用兩個下劃線相連,所以定義的模型屬性名不能包括多個下劃線
  • 實現sql中where的功能,可以呼叫過濾器filter()、exclude()、get()

查詢實現

  • 1.查詢id為1的書籍 (exact : 判斷相等)

      bookInfos = BookInfo.books.filter(id__exact=1)
    
  • 2.查詢書名包含‘湖’的書籍 (contains : 是否包含)

      bookInfos = BookInfo.books.filter(name__contains='湖')
    
  • 3.查詢書名以‘部’結尾的書籍 (startswith/endswith : 以什麼開頭/以什麼結尾)

      bookInfos = BookInfo.books.filter(name__endswith='部')
    
  • 4.查詢書名不為空的書籍 (isnull : 是否為null)

      bookInfos = BookInfo.books.filter(name__isnull=False)
    
  • 5.查詢編號為2或4的書籍(pk:主鍵/id) (in : 是否包含在範圍內)

      bookInfos = BookInfo.books.filter(pk__in=[2,4])
    
  • 6.查詢編號大於2的書籍(gt/大於、gte/大於等於、lt/小於、lte/小)

    bookInfos = BookInfo.books.filter(id__gt=2)

     

  • 7.查詢id不等於3的書籍 (exclude : 條件以外的資料)

      bookInfos = BookInfo.books.exclude(id=3)
    
  • 8.查詢1980年發表的書籍(year、month、day、week_day、hour、minute、second : 對日期時間型別的屬性進行運算)

    bookInfos = BookInfo.books.filter(pub_date__year=1980)
  • 9.查詢1990年1月1日後發表的書籍

  from datetime import date

  bookInfos = BookInfo.books.filter(pub_date__gt=date(1990,1,1))

提示:

  • exactcontainsstartswithendswith運算子都區分大小寫

  • 在這些運算子前加上i表示不區分大小寫

    • iexacticontainsistartswithiendswith

3.F和Q物件

F物件:用於兩個屬性的比較

語法:

from django.db.models import F

F('屬性名')

F物件查詢需求

  • 1.查詢閱讀量大於評論量的書籍

      bookInfos = BookInfo.books.filter(readcount__gt=F('commentcount'))
    
  • 2.查詢閱讀量大於2倍評論量的書籍 : F物件支援運算

      bookInfos = BookInfo.books.filter(readcount__gt=F('commentcount')*2)

Q物件:多個過濾器逐個呼叫表示邏輯與關係,同sql語句中where部分的and關鍵字

Q物件語法:

from django.db.models import Q

Q(模型屬性1__條件運算子=值) | Q(模型屬性2__條件運算子=值)

Q物件查詢需求

  • 1.查詢閱讀量大於20,或編號小於3的圖書

      bookInfos = BookInfo.books.filter(Q(readcount__gt=20) | Q(id__lt=3))
    
  • 2.查詢編號不等於3的書籍 (Q物件前可以使用~操作符,表示非not)

4.聚合函式

  • 使用aggregate()過濾器呼叫聚合函式,返回單個物件

  • 聚合函式包括:AvgMaxMinSumCount

    • 使用Count時,一般不需要 aggregate()過濾器,直接呼叫即可

  • 被定義在django.db.models

4.1 統計總的閱讀量

from django.db.models import Sum

def bookList(request):
    # 查詢編號不等於3的書籍
    bookInfos = BookInfo.books.filter(~Q(id=3))
    # 統計總的閱讀量
    readcount = BookInfo.books.aggregate(Sum('readcount'))

    # 構造上下文
    context = {'booklist':bookInfos,'readcount':readcount}
    return render(request, 'Book/booklist.html', context)

 注意上下文字典取總閱讀量時的key的書寫規則

5.關聯查詢

5.1基礎關聯查詢

  • 1.查詢編號為1的圖書中所有人物資訊

    • 通過書找關聯的人

      # 先查編號為1的書
      book = BookInfo.books.get(pk=1)
      # 再通過關聯查詢到編號為1的書裡面的任務資訊
      peopleInfos = book.peopleinfo_set.all()
      
  • 2.查詢編號為1的英雄出自的書籍

    • 通過人找關聯的書

      # 先查編號為1的人物
      people = PeopleInfo.objects.get(pk=1)
      # 再通過關聯查詢編號為1的人物對應的書
      bookInfo = people.book

5.2內連線查詢

語法如下 :

  關聯模型類名小寫__屬性名__運算子=值
  • 結果和sql中的inner join相同(內連線)

  • 1.查詢書名為"紅樓夢"的所有人物資訊(peopleInfo)

    • 通過書找關聯的人

      # 原始內連線sql語句:
      select p.name, b.name from peopleinfo as p inner join bookinfo as b on p.book_id = b.id where b.name = "紅樓夢";
      
      peopleInfos = PeopleInfo.objects.filter(book__name='紅樓夢')
      
  • 2.查詢書籍中人物的描述包含"紅"的書籍

    • 通過人找關聯的書

      bookInfos = BookInfo.books.filter(peopleinfo__description__contains='紅')

5.3自關聯查詢

  • 自關聯的表結構:對於地區資訊、分類資訊等資料,表結構非常類似,每個表的資料量十分有限,為了充分利用資料表的大量資料儲存功能,可以設計成一張表,內部的關係欄位指向本表的主鍵
  • 說明:關係屬性使用self指向本類,要求null和blank允許為空,因為一級資料是沒有父級的

  # 地區列表資訊
  class AreaInfo(models.Model):
      name = models.CharField(max_length=30) #名稱
      parent = models.ForeignKey('self',null=True,blank=True) #關係

      # 元類資訊 :修改表名
      class Meta:
          db_table = 'areainfo'