一、查詢集QuerySet
- 什么是查詢集耳幢?
查詢集:從數(shù)據(jù)庫查詢得到的模型對象集合QuerySet
岸晦,是一個列表 - 什么是過濾器?
過濾器:基于查詢集得到的結(jié)果上進(jìn)一步進(jìn)行條件篩選過濾結(jié)果
二睛藻、過濾器
返回list/多個結(jié)果的過濾器
-
values = model名稱.objects.all()
:返回所有數(shù)據(jù)启上;返回查詢集QuerySet
對象。因?yàn)槭橇斜淼暧。云浣Y(jié)果可以使用values[索引].字段名
獲取數(shù)據(jù)冈在。注意不支持負(fù)索引 -
model名稱.objects.retrieve()
:獲取數(shù)據(jù)表中的所有記錄,也就是返回查詢集QuerySet
對象 -
model名稱.objects.filter()
:返回滿足條件的數(shù)據(jù) -
model名稱.objects.exclude()
:返回滿足條件之外的數(shù)據(jù) -
model名稱.objects.order_by()
:返回排序后的結(jié)果
返回一個對象的過濾器
-
model名稱.objects.get()
:返回一個model
類按摘,而不是str
1.如果查詢不到對應(yīng)的結(jié)果包券, 則會拋出模型類.DoesNotExist
異常
2.如果返回多條結(jié)果,則會拋出模型類.MultipleObjectsReturned
異常 -
model名稱.objects.count()
:返回滿足查詢結(jié)果的總條數(shù) -
model名稱.objects.aggregate()
:返回集合 -
model名稱.objects.exists()
:判斷返回的查詢集中是否有數(shù)據(jù)炫贤,沒有則False
溅固,有則True
PS.
1.過濾器往往會和查詢條件結(jié)合使用進(jìn)行查詢
2.一般情況用model名稱.objects
,但也會指定對象兰珍,比如說polls.address.
查詢集的特點(diǎn)
- 非立刻執(zhí)行
1.創(chuàng)建查詢集時侍郭,并不會訪問數(shù)據(jù)庫。而是直到模板中調(diào)用到數(shù)據(jù)時,才會進(jìn)行數(shù)據(jù)庫的訪問亮元。 - 緩存
1.查詢集的結(jié)果會被保存下來猛计,再次查詢相同的數(shù)據(jù)時,會使用之前保存下來的結(jié)果數(shù)據(jù)
2.每個查詢集都會有一個緩存空間來保存查詢結(jié)果數(shù)據(jù)
3.切片和索引操作沒有緩存可用爆捞,每次都會實(shí)際去執(zhí)行sql語句
查詢集索引
當(dāng)查詢集返回的是列表時奉瘤,就可以使用下標(biāo)的方式來獲取我們想要的內(nèi)容。
def AddressAPI(request):
# 獲取第2嵌削、3毛好、4項(xiàng)
address_values = AddressInfo.objects.all()[1:3]
# 構(gòu)造上下文
context = {F'AddressInfo:{address_values}'}
return render(request, 'address.html', context)
三、查詢集的查詢條件
- 查詢語句:
模型屬性/表字段__條件運(yùn)算符=值
1.查詢語句由三部分組成:模型屬性/表字段
+兩個下劃線__
+條件運(yùn)算符苛秕,所以在定義屬性模型/表字段時肌访,不能定義包括多個下劃線的名字
2.想要實(shí)現(xiàn)SQL中的where功能,可以使用過濾器filter()
艇劫、exclude()
吼驶、get()
- 條件運(yùn)算符
1.exact
:判斷相等
address = AddressInfo.objects.filter(id__exact = 1) # 查詢id為1的地址
2.contains
:判斷包含
address = AddressInfo.objects.filter(name__contains = '廣') # 查詢地址名稱有廣的地址
3.startswith/endswith
:以什么開頭/結(jié)尾
4.isnull
:是否為null
address = AddressInfo.objects.filter(pid__isnull = true) # 查詢pid為null的地址
5.in
:是否包含在范圍內(nèi)
address = AddressInfo.address.filter(id__in = [1,3]) # 查詢id為1或3的地址
6.gt、gte店煞、lt蟹演、lte
:大于、大于等于顷蟀、小于酒请、小
7.exclude
:條件以外的數(shù)據(jù)
address = AddressInfo.objects.filter(id__exclude = 1) # 查詢id不為1的地址
8.year、month鸣个、day羞反、week_day、hour囤萤、minute昼窗、second
:對日期時間類型的屬性進(jìn)行查詢
books = BookInfo.objects.filter(pub_time__year = 2000) # 查詢2000年發(fā)表的書籍
9.datetime.date
from datetime import date
books = BookInfo.objects.filter(pub_time__gt = date(2000,1,1)) # 查詢2000年1月1號以后發(fā)布的書籍
10.多條件查詢:或(使用|
隔開查詢條件)
BookInfo.objects.filter(id__gt = 1 | pub_time__year = 2000) # 查詢id大于1或發(fā)布年份是2000年的數(shù)據(jù)
11.多條件查詢:與(使用,
隔開查詢條件)
BookInfo.objects.filter(id__gt = 1 , pub_time__year = 2000) # 查詢id大于1,并且發(fā)布年份是2000年的數(shù)據(jù)
12.鏈?zhǔn)讲樵儯憾鄠€filter()
進(jìn)行查詢(其它過濾器也可以這樣)
BookInfo.objects.filter(id__gt = 1).filter(pub_time__year = 2000) # 在查詢id大于1的結(jié)果集上涛舍,再查詢發(fā)布年份是2000年的數(shù)據(jù)
13.獲取查詢集的第一個元素以及最后一個元素:first()
澄惊、last()
BookInfo.objects.filter(id__gt = 1).first()
BookInfo.objects.filter(id__gt = 1).last()
14.排序order_by('字段/-字段')
BookInfo.objects.filter(id__gt = 1).order_by('name') # 結(jié)果按照name排序,ascall碼從小到大
BookInfo.objects.filter(id__gt = 1).order_by('-name') # 結(jié)果按照name排序富雅,ascall碼從大到小
BookInfo.objects.filter(id__gt = 1).order_by('id', 'name') # 結(jié)果先按照id排序掸驱,如果相同,則按照name排序
PS.
1.exact没佑、contains毕贼、startswith、endswith
這幾個運(yùn)算符都區(qū)分大小寫图筹,如需不區(qū)分大小寫帅刀,只需要在前面加上i
即可:iexact、icontains远剩、istartswitch扣溺、iendswith
四、F
對象和Q
對象
-
F
對象用于兩個屬性進(jìn)行比較瓜晤,并且支持運(yùn)算
1.語法:
from django.db.models import F
F("屬性名/表字段")
2.例子
2.1.查詢評論量大于閱讀量的書籍
books = BookInfo.objects.filter(commentcount__gt = F('readcount'))
2.2.查詢評論量大于閱讀量2倍的書籍
books = BookInfo.objects.filter(commentcount__gt = F('readcount' * 2))
-
Q
對象類似sql語句的where
中的and
或or
1.語法
from django.db.models import Q
# |:或
Q(屬性名/表字段1__條件運(yùn)算符=值) | Q(屬性名/表字段2__條件運(yùn)算符=值) # 查詢滿足第一個條件或第二個條件的數(shù)據(jù)
# ,:且
Q(屬性名/表字段1__條件運(yùn)算符=值) , Q(屬性名/表字段2__條件運(yùn)算符=值) # 查詢滿足第一個條件和第二個條件的數(shù)據(jù)
# 組合
Q(屬性名/表字段1__條件運(yùn)算符=值) , Q(屬性名/表字段2__條件運(yùn)算符=值) | Q(屬性名/表字段3__條件運(yùn)算符=值) # 查詢滿足條件1且(條件2或條件3)的數(shù)據(jù)
2.1.或:|
books = BookInfo.objects.filter(Q(readcount__gt = 10) | Q(id__lt) = 5) # 查詢閱讀量大于10或id小于5的書籍
2.2.且:,
books = BookInfo.objects.filter(Q(readcount__gt = 10) , Q(id__lt) = 5) # 查詢閱讀量大于10且id小于5的書籍
2.3.不等于/取反:~
books = BookInfo.objects.filter(~Q(readcount__gt = 10) , Q(id__lt) = 5) # 查詢閱讀量小于等于10且id小于5的書籍
2.4.組合
略
PS.如果有其它關(guān)鍵字條件锥余,Q
對象需要在關(guān)鍵字條件后面
books = BookInfo.objects.filter(pub_time = 2000 , Q(id__lt) = 5) # pub_time是關(guān)鍵字
關(guān)于Q
對象更詳細(xì)看文章:https://www.cnblogs.com/huchong/p/8027962.html
五、聚合函數(shù)
-
aggregate()
過濾器調(diào)用聚合函數(shù)痢掠,然后返回單個對象 - 聚合函數(shù):
Avg('屬性名/表字段')
驱犹、Max('屬性名/表字段')
、Min('屬性名/表字段')
足画、Sum('屬性名/表字段')
雄驹、Count('屬性名/表字段')
。使用Count('屬性名/表字段')
時淹辞,一般情況下是直接調(diào)用医舆,不需要使用aggregate()
函數(shù) - 聚合函數(shù)在
django.db.models
導(dǎo)入 - 例子(注意上下文字典中,總閱讀量的key的書寫規(guī)則)
from django.db.models import Sum
def books(request):
# 統(tǒng)計(jì)所有書籍的總閱讀量
readcount = BookInfo.objects.aggregate(Sum('readcount'))
# 構(gòu)造上下文
context = {'readcount': readcount}
return render(request, 'Book/book.html', context)
六象缀、關(guān)聯(lián)查詢(objects
前面用的是哪個class蔬将,返回的就是哪個class對象)
一對多、多對多關(guān)聯(lián)查詢(基礎(chǔ)關(guān)聯(lián))
- 查詢方老師所教的所有課程
# 先查詢方老師
teacher = Teacher.objects.get(nickname = '方老師')
# 再通過方老師查詢所有相關(guān)的任務(wù)信息
classInfo = teacher.classinfo_set.all()
- 查詢python課程的老師
# 先查詢課程
class = ClassInfo.object.get(title = 'python課程')
# 再通過關(guān)聯(lián)查詢對應(yīng)的老師
teacher = class.teacher
內(nèi)連接查詢
- 語法:
外鍵字段名__從表字段名__條件
或關(guān)聯(lián)模型類名小寫__屬性名__運(yùn)算符=值
央星,結(jié)果和sql中的inner join
相同(內(nèi)連接) - 查詢書名為"紅樓夢"的所有人物信息(peopleInfo)
通過書找關(guān)聯(lián)的人
# 原始內(nèi)連接sql語句:
select p.name, b.name from peopleinfo as p inner join bookinfo as b on p.book_id = b.id where b.name = "紅樓夢";
對應(yīng)語句:
peopleInfos = PeopleInfo.objects.filter(book__name='紅樓夢')
- 查詢書籍中人物的描述包含"紅"的書籍
通過人找關(guān)聯(lián)的書
bookInfos = BookInfo.books.filter(peopleinfo__description__contains='紅')
自關(guān)聯(lián)查詢
自關(guān)聯(lián)的表結(jié)構(gòu):對于地區(qū)信息霞怀、分類信息等數(shù)據(jù),表結(jié)構(gòu)非常類似莉给,每個表的數(shù)據(jù)量十分有限毙石,為了充分利用數(shù)據(jù)表的大量數(shù)據(jù)存儲功能,可以設(shè)計(jì)成一張表禁谦,內(nèi)部的關(guān)系字段指向本表的主鍵
說明:關(guān)系屬性使用self指向本類胁黑,要求null和blank允許為空,因?yàn)橐患墧?shù)據(jù)是沒有父級的
更多看之前的文章:http://www.reibang.com/p/08c1be3dc9b2
七州泊、LIKE語句中轉(zhuǎn)義百分符號和下劃線
在sql語句中丧蘸,%
有特殊的作用,Django可以轉(zhuǎn)義%
和_
遥皂,這樣就可以和普通字符一樣使用
xxx.objects.filter(headline__contains='%')
# 相當(dāng)于sql:
SELECT ... WHERE headline LIKE '%\%%';
八力喷、創(chuàng)建數(shù)據(jù)/生成數(shù)據(jù)表中的數(shù)據(jù)
- 創(chuàng)建和保存對象
#### 方法1
# 1.創(chuàng)建模型類對象,此時sql還未執(zhí)行
one_value = Userinfo(username='hello', password='hi')
# 2.調(diào)用save方法演训,執(zhí)行sql語句弟孟,生成數(shù)據(jù)
one_value.save()
#### 方法2
# 執(zhí)行sql語句,生成數(shù)據(jù)样悟,返回的是模型類對象
Userinfo.objects.create(username='hi', password='hello')
- 保存外鍵字段
保存外鍵字段和保存普通字段一樣拂募,只不過給外鍵字段賦值的時候迅速要注意類型要正確 - 保存多對多字段
需要調(diào)用add()
方法庭猩,而不是直接給屬性賦值,不過不需要調(diào)用save()
方法
from .model.animal import Animal
from .model.cat import Cat
animal = Animal.objects.get(pk = 1)
cat1 = Cat.objects.create(named='xiaomi')
cat2 = Cat.objects.create(named='xiaohei')
animal.cats.add(cat1, cat2) # 保存多對多字段
八陈症、修改數(shù)據(jù)和更新數(shù)據(jù)
- 修改數(shù)據(jù):先獲取數(shù)據(jù)蔼水,然后修改數(shù)據(jù),再保存數(shù)據(jù)(一般用于外鍵/
ForeignKey
的修改)
value = Animal.objects.get(id=1)
value.namede = 'haha'
value.save()
- 更新數(shù)據(jù):
update()
1.可以批量為QuerySet
中所有的對象進(jìn)行更新操作
2.只能對普通字段和ForeignKey
字段使用
3.對ForeignKey
字段使用時录肯,需要設(shè)置新值為想要指向的新模型實(shí)例
# 普通字段
Animal.objects.filter(id=1).update(named = 'hahaha')
# ForeignKey字段
c = Cat.objects.get(id=2) # 想要指向的新模型實(shí)例
Animal.objects.all().update(cat=c)
-
update()
方法會直接轉(zhuǎn)換成一個sql語句趴腋,并立刻批量執(zhí)行,并且不會運(yùn)行模型的save()
方法论咏。如果想要保存QuerySet
中的每個條目并確保每個實(shí)例的save()
方法都被調(diào)用优炬,你不需要使用任何特殊的函數(shù)來處理。只需要迭代它們并調(diào)用save()
方法:
for item in my_queryset:
item.save()
-
update
方法可以配合F表達(dá)式厅贪。這對于批量更新同一模型中某個字段特別有用蠢护。例如增加Blog中每個Entry的pingback個數(shù):
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
。然而养涮,與filter
和exclude
子句中的F()
對象不同糊余,在update
中不可以使用F()
對象進(jìn)行跨表操作,只可以引用正在更新的模型的字段单寂。如果嘗試使用F()
對象引入另外一張表的字段贬芥,將拋出FieldError
異常:
# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))
九、刪除數(shù)據(jù)
先獲取數(shù)據(jù)宣决,再刪除數(shù)據(jù)
value = Animal.objects.get(id=1)
value.delete() # 該方法將返回被刪除對象的總數(shù)量和一個字典蘸劈,字典包含了每種被刪除對象的類型和該類型的數(shù)量
# 支持批量刪除
Animal.objects.filter(named='haha').delete()
- 注意
delete()
是唯一沒有在管理器上暴露出來的方法。這是刻意設(shè)計(jì)的一個安全機(jī)制尊沸,用來防止意外地請求類似Animal.objects.delete()
的動作威沫,導(dǎo)致不慎刪除了所有的對象數(shù)據(jù)。如果你確實(shí)想刪除所有的對象洼专,你必須明確地請求一個完全的查詢集棒掠,如:
Animal.objecets.all().delete()
PS.本文參考:
https://blog.csdn.net/kan2016/article/details/82868636/、https://www.cnblogs.com/huchong/p/8027962.html