django學習第八天
阿新 • • 發佈:2020-07-21
orm多條操作
刪除和修改
- 修改
在一對一和一對多關係時,和單表操作是一樣的 一對一 一個作者對應一個資訊 ad_obj = models.AuthorDetail.objects.get(id=1) models.Author.objects.filter(id=1).update(name='xx',屬性名=模型類物件) models.Author.objects.filter(id=1).update(name='xx',ad=ad_obj) models.Author.objects.filter(id=1).update(name='xx',欄位名=id欄位值) models.Author.objects.filter(id=1).update(name='xx',ad_id=1) 一對多 一個出版社出多本書 pub_obj = models.Publish.objects.get(id=2) models.Book.objects.filter(id=1).update(title='水滸',屬性名=模型類物件) models.Book.objects.filter(id=1).update(title='水滸',pub=pub_obj) models.Book.objects.filter(id=2).update(title='三國',欄位名=id欄位值) models.Book.objects.filter(id=2).update(title='三國',pub_id=2) 多對多修改 book_obj = models.Book.objcets.get(id=4) #用book_obj模型類物件,然後點屬性(.authors)的方式操作第三張表 book_obj.authors.set('3')#引數要是可迭代型別資料 book_obj.authors.set([3,])#更新多個記錄 set執行的步驟: 1.先執行clear清空 2.再執行add新增 book_obj = models.Book.objects.get(id=1) book_obj.authors.set([4,])
- 刪除
一對一和一對多刪除一樣 delete方法 models.Author.objects.filter(id=1).delete() models.AuthorDetail.objects.filter(id=1).delete() 多對多刪除remove book_obj = models.Book.objects.get(id=1) author_obj = models.Author.objects.get(id=2) 下面orm語句意思為在多對多關係表中刪除了書籍id為1的,作者id為2的記錄 #通過Book得到的模型類物件點屬性(.authors)操作第三張表 book_obj.authors.remove(2) #刪除單條 book_obj.authors.remove(2,3)#刪除多條
- 清空
多對多
#將當前書籍對應的所有作者在多對多關係表中的關係記錄,全部刪除
book_obj = models.Book.objects.get(id=1)
book_obj.authors.clear()
子查詢和連表查詢
基於物件的跨表查詢(子查詢)
一對一查詢 正向查詢 關係屬性寫在哪個表裡面,那麼通過這個表的資料,去查詢關聯的另外一張表的資料,就叫作正向查詢,反之就是反向查詢 #正向查詢使用關聯屬性名稱 #查詢一下王振這個作者的手機號 author_obj = models.Author.objects.get(name='王振') author_obj.ad #找到了author_obj關聯的作者詳細資訊表裡面的對應記錄 主表模型類物件(author_obj).主表的關聯屬性名稱(ad).從表屬性名(telephone) print(author_obj.ad.telephone) #反向查詢 反向查詢用關聯它的模型類的名稱小寫 查詢一下地址在上海的那個作者是誰 從表->主表 author_detail_obj = models.AuthorDetail.objects.filter(address='上海').first() #filter過濾後的是quertset型別,用first取第一個模型類物件 從表的模型類物件.主表的模型類名稱小寫.主表屬性名 print(author_detail_obj.author.name) ##########一對多######### #正向查詢 #使用關聯屬性查詢 #查詢一下少年阿賓是哪個出版社出版的 book_obj = models.Book.objects.get(title='少年阿賓') Book類的模型類物件.關聯屬性.name print(book_obj.pub.name) #反向查詢 #模型類小寫_set #查詢一下偉哥出版社出版了哪些書 pub_obj = models.Publish.objects.get(name='偉哥出版社') pub_obj.book_set #可能為多條記錄,所以模型類名小寫_set #類似於objects控制器 print(pub_obj.book_set.all().values('title')) #查詢結果不會自動去重 ######多對多###### #正向查詢 #使用屬性來查 #查詢一下金陵第二步這本書誰寫的 book_obj = models.Book.objects.get(title='金陵第二部') Book類的模型類物件.關聯屬性名稱.all().values('name') print(book_obj.authors.all().values('name')) #反向查詢 #使用模型類名小寫_set 查詢一下謝晨寫了哪些書 author_obj = models.Author.objects.get(name='謝晨') print(author_obj.book_set.all().values('title'))
檢視原生sql的方式
- 1.query 適用於大部分
- 2.在settings配置檔案中寫上如下內容,就能夠自動打印出我們執行orm語句對應的sql
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
- 3.通過django配置的連線mysql的管道來檢視(pymysql)
from app01 import models
def add_book(request):
book_obj = models.Book(title='python',price=123)
book_obj.save()
from django.db import connection #通過這種方式也能檢視sql語句
print(connection.queries)
return HttpResponse('OK')
基於雙下劃線的跨表查詢(連表操作)
原生sql寫法 哪個表在前哪個表在後沒區別
select * from t2 inner join t1 on t1.t2_id = t2.id;
select * from t1 inner join t2 on t1.t2_id = t2.id;
- 一對一
查詢一下謝思敏這個作者的家庭地址
正向操作,使用屬性
ret = models.Author.objects.filter(過濾條件).values('主表屬性名__從表屬性名')
ret = models.Author.objects.filter(name='謝思敏').values('ad__address') #<QuerySet [{'ad__address': '美國'}]>型別
反向操作,使用表名小寫
ret = models.AuthorDetail.objects.filter(主表表名小寫__過濾條件).values('從表屬性名')
ret = models.AuthorDetail.objects.filter(author__name='謝思敏').values('address') #<QuerySet [{'address': '美國'}]>型別
- 一對多
查詢一下少年阿賓是哪個出版社出版的
正向操作 使用關聯屬性
#這類的正向操作,注意看關聯的屬性名在哪個表裡,哪個表就是主表
ret = models.Book.objects.filter(過濾條件).values('關聯屬性名__從表屬性名')
ret = models.Book.objects.filter(title='少年阿賓').values('pub__name')#<QuerySet [{'pub__name': '橘子成人出版社'}]>
反向操作
ret = models.Publish.objects.filter(主表類名小寫__過濾條件).values('從表屬性名')
ret = models.Publish.objects.filter(book__title='少年阿賓').values('name')#<QuerySet [{'name': '橘子成人出版社'}]>
- 多對多
查詢一下金陵第二部這本書誰寫的
正向操作 使用關聯屬性
ret = models.Book.objects.filter(title='金陵第二部').values('Book類模型關聯屬性__author表屬性名')
ret = models.Book.objects.filter(title='金陵第二部').values('authors__name')
#<QuerySet [{'authors__name': '謝思敏'}, {'authors__name': '謝晨'}]>
反向操作 使用類名小寫
ret = models.Author.objects.filter(主表類名小寫__過濾條件).values('從表屬性名')
ret = models.Author.objects.filter(book__title='金陵第二部').values('name')
#<QuerySet [{'name': '謝思敏'}, {'name': '謝晨'}]>
聚合查詢(aggregate)
##########聚合查詢aggregate###########
統計一下所有書籍的平均價格 max min avg count sum
需要先匯入
from django.db.models import Max,Min,Avg,Count,Sum
ret = models.Book.objects.aggregate(Avg('price'))
print(ret)#普通字典型別{'price__avg': 43.925}
ret = models.Book.objects.all().aggregate(a=Avg('price'),b=Max('price'))
print(ret)#{'price__avg': 43.925, 'price__max': Decimal('88.88')} , {'a': 43.925, 'b': Decimal('88.88')}
#aggregate方法可以看為是orm語句的結束語句,結果為普通字典型別,不能繼續呼叫queryset或者模型類物件提供的方法了,也就是aggregate必須放在最後,另外裡面的聚合函式可以賦值給變數
分組查詢(annotate)
###########分組查詢###########
查詢一下每個出版社出版書的平均價格
ret = models.Book.objects.values('要分組的欄位名').annotate(聚合函式)
ret = models.Book.objects.values('pub_id').annotate(a=Avg('price'))#只能獲取到values指定的欄位和統計結果資料
ret = models.Book.objects.values('pub_id','id').annotate(a=Avg('price'))#多條件分組pub_id和id值相同的算為一組
values('pub__name')#就是通過Book類的屬性名跨表操作另外一張表的name
ret = models.Book.objects.values('pub__name').annotate(a=Avg('price'))#以出版社名稱分組
#推薦使用下面的因為獲取到模型類物件就可以用它所有的屬性資料
ret = models.Publish.objects.annotate(變數a=聚合函式Avg('要關聯的另外一張表的類名小寫__要操作的屬性'))
ret = models.Publish.objects.annotate(a=Avg('book__price'))#返回結果是Publish的模型類物件,這個模型類物件裡面包含了Publish的所有屬性資料,還有annotate的統計結果資料
ret = models.Publish.objects.annotate(a=Avg('book__price')).values('name','a')
原生sql,虛擬碼
select publish.name,Avg(book.price) from publish inner join book on publish.id = book.pub_id group by publish.id.
select avg(price) from book group by pub_id;
F查詢 主要針對本表的多個欄位進行比較時使用
########F查詢#########
from django.db.models import F
#查詢一下點贊數在於評論數的書籍
models.Book.objects.filter(dianzan__gt=comment)
obj_list = models.Book.objects.all().values()
a = []
for i in obj_list:
if i.dianzan > i.comment:
a.append(i)
print(a)
#上面寫法太麻煩了
F查詢可以用來做本表不同欄位之間的一個比較
ret = models.Book.objects.filter(dianzan__gt=F('comment'))
print(ret)
F可以用來對本表資料進行一些同一操作(四則執行都支援)
將所有的書籍上調10塊錢
models.Book.objects.all().update(price=F('price')+10)
Q查詢 可以進行多條件查詢,查詢關係可以是 或與非
from django.db.models import F
#查詢書名中包含少年兩個字的並且評論數大於20的書籍
ret = models.Book.objects.filter(title__contains='少年',comment__ge=20)
#filter中逗號分隔的條件,預設是and的關係
print(ret)#<QuerySet [<Book: 少年阿賓2>]>
#想進行或的關係查詢需要藉助到我們Q查詢Q
查詢書名中包含少年兩個字的或者評論數大於20的書籍
ret = models.Book.objects.filter(Q(title__contains='少年')|Q(comment__gt=20))
查詢書名中包含少年兩個字的或者評論數大於20的,並且點贊數大於等於80的
ret = models.Book.objects.filter(Q(title__contains='少年')|Q(comment__gt=20),dianzan__gte=80)
#注意,如果結合逗號來進行and的關係查詢,那麼必須將沒有Q包裹的查詢條件放在Q包裹的查詢條件後面
下面這張方式也可以,Q查詢可以多層巢狀使用
# ~取反 &and關係 |or關係
ret = models.Book.objects.filter(Q(Q(title__contains='少年')|Q(comment__gt=20)) & ~Q(dianzan__gte=80))