<1> all(): 查詢全部結果 <2> filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 <3> get(**kwargs): 返回與所給篩選條件相匹配的對象 返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 <4> exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 <5> values(*field): 返回一個ValueQuerySet, 運行後獲得的不是一系列model的實例化對象,而是一個可迭代的字典序列 <6> values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 <7> order_by(*field): 對查詢結果排序 <8> reverse(): 對查詢結果反向排序,請注意reverse()一般只能在具備已定義順序的QuerySet上調用 (在model類的Meta中指定ordering或調用order_by()方法)。 <9> distinct(): 從返回結果中剔除重複紀錄 (若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果此時可使用distinct(), 注意只有在PostgreSQL中支持按字段去重。) <10> count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 <11> first(): 返回第一條記錄 .all().first 等效於 .first() <12> last(): 返回最後一條記錄 <13> exists(): 若是QuerySet包含數據,就返回True,不然返回False
all() filter() exclude() order_by() reverse() distinct()
values() 返回一個可迭代的字典序列 values_list() 返回一個可迭代的元祖序列
具體的對象是沒法使用這兩個方法的 原理上來講models.py 裏面的 class類 中就沒有 這兩個屬性 這兩個屬性只針對於一個QuerySet序列集進行篩選才可使用 好比 .filter(id=1) 雖然只返回了一個QuerySet對象 可是也可使用
get() first() last()
對象能夠直接 .屬性 的方法去取值 原理上來講在數據庫對象的裏面就有屬性天然是能夠知己調用的
exists()
count()
具體對象python
QuerySet對象linux
轉換sql
QuerySet對象------>具體對象數據庫
QuerySet對象.first()django
QuerySet對象[0]緩存
# 查詢 "部門表" 的所有內容 # 查詢的時候不帶 values或者values_list 默認就是查詢 all() ret = models.Employee.objects.all() # """ # SELECT `employee`.`id`, `employee`.`name`, `employee`.`age`, `employee`.`salary`, `employee`.`province`, `employee`.`dept` FROM `employee` LIMIT 21; args=() # """ # 查詢全部人的 "部門" 和 "年齡" # values 或者 values_list 裏面寫什麼就至關於 select 什麼字段 ret = models.Employee.objects.all().values("dept", "age") # """ # SELECT `employee`.`dept`, `employee`.`age` FROM `employee` LIMIT 21; args=() # """
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 獲取name字段包含"ven"的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id範圍是1到3的,等價於SQL的bettwen and 左右都包含 # 相似的還有:startswith,istartswith, endswith, iendswith # date字段還能夠單獨將年月日拿出來 models.Class.objects.filter(birtday__year=2017) models.Class.objects.filter(birtday__month=7) models.Class.objects.filter(birtday__day=17)
正向查詢,按字段app
book_obj.publish : 與這本書關聯的出版社對象
book_obj.publish.addr: 與這本書關聯的出版社的地址
反向查詢,按表名_setide
publish_obj.book_set: 與這個出版社關聯的書籍對象集合
publish_obj.book_set.all() :[obj1,obj2,....]
正向查詢,按字段函數
author_obj.ad : 與這個做者關聯的做者詳細信息對象
反向查詢:按表名fetch
author_detail_obj.author : 與這個做者詳細對象關聯的做者對象
正向查詢,按字段
book_obj.authorList.all(): 與這本書關聯的全部這做者對象的集合 [obj1,obj2,....] book_obj.authorList.all().values("name"): 若是想查單個值的時候能夠這樣查
反向查詢,按表名_set
author_obj.book_set.all() : 與這個做者關聯的全部書籍對象的集合 book_obj.book_set.all().values("name"): 若是想查單個值的時候能夠這樣查
正向查詢,按字段
# 查詢linux這本書的出版社的名字: models.Book.objects.all().filter(title="linux").values("publish__name")
反向查詢:按表名
# 查詢人民出版社出版過的全部書籍的名字 models.Publish.objects.filter(name="人民出版社出版").values("book__title")
正向查詢,按字段
#查詢egon的手機號 models.Author.objects.filter(name="egon").values("ad__tel")
反向查詢:按表名
#查詢手機號是151的做者 models.AuthorDetail.objects.filter(tel="151").values("author__name")
正向查詢,按字段
#查詢python這本書的做者的名字 models.Book.objects.filter(title="python").values("authorList__name") [{},{},{},{}]
反向查詢,按表名
#查詢alex出版過的出的價格 models.Author.objects.filter(name="alex").values("book__price")
ps:
若是喲有設置,反向查詢的時候都用:related_name 的值
publish=models.ForeignKey("Publish",related_name="bookList") authorlist=models.ManyToManyField("Author",related_name="bookList") ad=models.models.OneToOneField("AuthorDetail",related_name="authorInfo")
利用 關聯管理器 進行維護
建立一個新的對象,保存對象,並將它添加到關聯對象集之中,返回新建立的對象。
models.Author.objects.first().book_set.create(title="羊駝之歌", publish_id=2)
把指定的model對象添加到關聯對象集中。
添加對象 >>> author_objs = models.Author.objects.filter(id__lt=3) >>> models.Book.objects.first().authors.add(*author_objs)
添加id >>> models.Book.objects.first().authors.add(*[1, 2])
更新model對象的關聯對象。
book_obj = models.Book.objects.first() book_obj.authors.set([2, 3])
從關聯對象集中移除執行的model對象
book_obj = models.Book.objects.first() author_obj.books.remove(book_obj) author_obj.books.remove(8) # 把id = 8 的書刪掉
從關聯對象移除一切對象。
book_obj = models.Book.objects.first() book_obj.authors.clear()
注意:
對於ForeignKey對象,clear()和remove()方法僅在null=True時存在。
# ForeignKey字段沒設置null=True時, class Book(models.Model): title = models.CharField(max_length=32) publisher = models.ForeignKey(to=Publisher) # 沒有clear()和remove()方法: >>> models.Publisher.objects.first().book_set.clear() Traceback (most recent call last): File "<input>", line 1, in <module> AttributeError: 'RelatedManager' object has no attribute 'clear' # 當ForeignKey字段設置null=True時, class Book(models.Model): name = models.CharField(max_length=32) publisher = models.ForeignKey(to=Class, null=True) # 此時就有clear()和remove()方法: dels.Publisher.objects.first().book_set.clear()
注意
對於全部類型的關聯字段,add()、create()、remove() 和 clear(), set() 都會立刻更新數據庫。
換句話說,在關聯的任何一端,都不須要再調用save()方法。
1 from django.shortcuts import render,HttpResponse 2 3 # Create your views here. 4 5 6 from app01 import models 7 8 def query(request): 9 10 # #####################基於對象查詢(子查詢)############################## 11 # 按字段(publish) 12 # 一對多 book -----------------> publish 13 # <---------------- 14 # book_set.all() 15 16 # 正向查詢按字段: 17 18 # 查詢python這本書籍的出版社的郵箱 19 20 # python=models.Book.objects.filter(title="python").first() 21 # print(python.publish.email) 22 23 24 # 反向查詢按 表名小寫_set.all() 25 26 # 蘋果出版社出版的書籍名稱 27 28 # publish_obj=models.Publish.objects.filter(name="蘋果出版社").first() 29 # for obj in publish_obj.book_set.all(): 30 # print(obj.title) 31 32 # 按字段(authors.all()) 33 # 多對多 book -----------------------> author 34 # <---------------- 35 # book_set.all() 36 37 38 # 查詢python做者的年齡 39 # python = models.Book.objects.filter(title="python").first() 40 # for author in python.authors.all(): 41 # print(author.name ,author.age) 42 43 # 查詢alex出版過的書籍名稱 44 45 # alex=models.Author.objects.filter(name="alex").first() 46 # for book in alex.book_set.all(): 47 # print(book.title) 48 49 # 按字段 authorDetail 50 # 一對一 author -----------------------> authordetail 51 # <---------------- 52 # 按表名 author 53 54 55 #查詢alex的手機號 56 # alex=models.Author.objects.filter(name='alex').first() 57 # print(alex.authorDetail.telephone) 58 59 60 # 查詢家在山東的做者名字 61 62 # ad_list=models.AuthorDetail.objects.filter(addr="shandong") 63 # 64 # for ad in ad_list: 65 # print(ad.author.name) 66 67 68 69 ''' 70 對應sql: 71 72 select publish_id from Book where title="python" 73 select email from Publish where nid = 1 74 75 76 ''' 77 78 79 80 81 # #####################基於queryset和__查詢(join查詢)############################ 82 83 # 正向查詢:按字段 反向查詢:表名小寫 84 85 86 # 查詢python這本書籍的出版社的郵箱 87 # ret=models.Book.objects.filter(title="python").values("publish__email") 88 # print(ret.query) 89 90 ''' 91 select publish.email from Book 92 left join Publish on book.publish_id=publish.nid 93 where book.title="python" 94 ''' 95 96 # 蘋果出版社出版的書籍名稱 97 # 方式1: 98 ret1=models.Publish.objects.filter(name="蘋果出版社").values("book__title") 99 print("111111111====>",ret1.query) 100 #方式2: 101 ret2=models.Book.objects.filter(publish__name="蘋果出版社").values("title") 102 print("2222222222====>", ret2.query) 103 104 #查詢alex的手機號 105 # 方式1: 106 ret=models.Author.objects.filter(name="alex").values("authorDetail__telephone") 107 108 # 方式2: 109 models.AuthorDetail.objects.filter(author__name="alex").values("telephone") 110 111 # 查詢手機號以151開頭的做者出版過的書籍名稱以及書籍對應的出版社名稱 112 113 ret=models.Book.objects.filter(authors__authorDetail__telephone__startswith="151").values('title',"publish__name") 114 print(ret.query) 115 116 117 return HttpResponse("OK")
惰性執行
books = BookInfo.objects.all() # 此時,數據庫並不會進行實際查詢 # 只有當真正使用時,如遍歷的時候,纔會真正去數據庫進行查詢 for b in books: print(b)
緩存
# 進行數據庫實際查詢遍歷,保存結果到bs,會進行數據庫實際交互 bs = [b.id for b in BookInfo.objects.all()] # 再次調用緩存結果bs,再也不進行數據庫查詢,而是使用緩存結果
exists()
簡單的使用if語句進行判斷也會徹底執行整個queryset而且把數據放入cache,雖然你並不須要這些數據!爲了不這個,能夠用exists()方法來檢查是否有數據:
if queryResult.exists(): #SELECT (1) AS "a" FROM "blog_article" LIMIT 1; args=() print("exists...")
iterator()
當queryset很是巨大時,cache會成爲問題。
處理成千上萬的記錄時,巨大的queryset可能會鎖住系統進程,讓你的程序瀕臨崩潰。
要避免在遍歷數據的同時產生queryset cache,可使用 iterator() 方法 來獲取數據,處理完數據就將其丟棄
objs = Book.objects.all().iterator() # iterator()能夠一次只從數據庫獲取少許數據,這樣能夠節省內存 for obj in objs: print(obj.title) # 基於迭代器的特性,被遍歷到底部以後下次在使用是無效的了。 for obj in objs: print(obj.title)
使用 .iterator() 來防止生成cache,意味着遍歷同一個queryset時會重複執行查詢.
因此使 用 .iterator() 時需確保操做一個大queryset時沒有重複執行查詢.
Queryset的cache是用於減小程序對數據庫的查詢,在一般的使用下會保證只有在須要的時候纔會查詢數據庫。
使用exists()和iterator()方法能夠優化程序對內存的使用。不過,因爲它們並不會生成queryset cache,可能 會形成額外的數據庫查詢。
from django.db.models import Avg, Sum, Max, Min, Count
>>> from django.db.models import Avg, Sum, Max, Min, Count >>> models.Book.objects.all().aggregate(Avg("price")) {'price__avg': 13.233333}
# 指定名稱 >>> models.Book.objects.aggregate(average_price=Avg('price')) {'average_price': 13.233333} # 屢次聚合 >>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price")) {'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}
aggregate 返回的是一個字典,而不是queryset 對象
Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg")
# 每一個 「省」 的 「平均工資」 , 查詢後的結果爲 「省 : 平均工資 」 # annotate前面是什麼就按照什麼來分組,annotate後面的字段是被分組後被計算的新增數據列, ret = models.Employee.objects.values("province").annotate(a=Avg("salary")).values("province", "a") # """ # SELECT `employee`.`province`, AVG(`employee`.`salary`) AS `a` FROM `employee` GROUP BY `employee`.`province` ORDER BY NULL LIMIT 21; args=() # """
# 統計每一本書的做者個數 book_list = models.Book.objects.all().annotate(author_num=Count("author")) # 統計出每一個出版社買的最便宜的書的價格 publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price")) publisher_list = models.Book.objects.values("publisher__name").annotate(min_price=Min("price")) # 統計不止一個做者的圖書 book_list = models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1) # 根據一本圖書做者數量的多少對查詢集 QuerySet進行排序 book_list = models.Book.objects.annotate(author_num=Count("author")).order_by("author_num") # 查詢各個做者出的書的總價格 author_list = models.author.annotate(sum_price=Sum("book__price")).values("name", "sum_price"))
# ORM連表分組查詢 # 根據 "部門" 計算出 "平均工資" 結果爲顯示爲 "部門名字 : 平均工資" 的表 ret = models.Person.objects.values("dept_id").annotate(a=Avg("salary")).values("dept__name", "a") # """ # SELECT `dept`.`name`, AVG(`person`.`salary`) AS `a` FROM `person` INNER JOIN `dept` ON (`person`.`dept_id` = `dept`.`id`) GROUP BY `person`.`dept_id`, `dept`.`name` ORDER BY NULL LIMIT 21; args=() # """
查詢每一個部門的員工的員工數
查詢每一個部門的員工總工總人數
對於基礎的兩個值得比較能夠經過上面的方法實現
可是對於兩個字段的比較則須要用到 F 查詢
# 查詢評論數大於收藏數的書籍 from django.db.models import F models.Book.objects.filter(commnet_num__gt=F('keep_num')) # Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。 models.Book.objects.filter(commnet_num__lt=F('keep_num')*2) # 對整個字段的全部值的操做也能夠經過 F 函數實現 # 好比將每一本書的價格提升30元 models.Book.objects.all().update(price=F("price")+30)
關於修改 char 字段的操做
# 把全部書名後面加上(初版) >>> from django.db.models.functions import Concat >>> from django.db.models import Value >>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("初版"), Value(")")))
當使用filter 的時候 ,內部多個篩選條件是 and 的關係
若需求爲 or 的關係須要用到 Q 查詢
# 查詢做者名是羊駝或山羊的 models.Book.objects.filter(Q(authors__name="羊駝")|Q(authors__name="山羊"))
# 能夠組合& 和| 操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢。
# 查詢做者名字是羊駝之歌而且不是2018年出版的書的書名。 models.Book.objects.filter(Q(author__name="羊駝之歌") & ~Q(publish_date__year=2018)).values_list("title")
當 and 和 or 同時一塊兒用的時候 , Q 查詢須要放在前面
示例
# 查詢出版年份是2017或2018,書名中帶羊駝的全部書。 models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="羊駝")
此方法比一般使用稍微複雜一些。本質上和 .filter(Q(title="yang")|Q(price=123)) 實現效果相同,
可是 這樣子拆分出來能夠實現 不在使用字段對象,而是用字符串來篩選
場景適用:
搜索框獲取當前get 請求中的參數時,參數爲字符串形式,用常規的Q查詢必須依靠字段對象從而沒法實現
q = Q() # 將Q實例化對象單獨拿出來 q.connnection = "or" # 默認多條件的關係是 "and" 經過connection 能夠改爲其餘 q.children.append(("title", "yang")) # 添加查詢字段 q.children.append(("price", 123))
限制住當前查詢結束後才能夠其餘的操做.保證數據的可靠性
select_for_update(nowait=False, skip_locked=False)
示例
entries = Entry.objects.select_for_update().filter(author=request.user)
1 # 查詢person表,判斷每一個人的工資是否大於2000 2 # 利用子查詢,能夠寫入原生的sql語句 3 ret = models.Person.objects.all().extra( 4 select={"gt": "salary > 2000"} 5 ) 6 7 # """ 8 # SELECT (salary > 2000) AS `gt`, `person`.`id`, `person`.`name`, `person`.`salary`, `person`.`dept_id` FROM `person` LIMIT 21; args=() 9 # """ 10 11 for i in ret: 12 print(i.name, i.gt)
1 # 執行徹底的原生的SQL語句,相似pymql 2 from django.db import connection 3 cursor = connection.cursor() # 獲取光標,等待執行SQL語句 4 cursor.execute("""SELECT * from person where id = %s""", [1]) 5 row = cursor.fetchone() 6 print(row)