Django框架第七篇(模型層)--多表操做:一對多/多對多增刪改,跨表查詢(基於對象、基於雙下劃線跨表查詢),聚合查詢,分組查詢,F查詢與Q查詢

1、多表操做mysql

一對多字段的增刪改(book表和publish表是一對多關係,publish_id字段)sql

若是是數據庫實際字段就傳數字,不是就傳對象數據庫

增  createdjango

publish_id 傳數字     (publish_id是數據庫顯示的字段名,外鍵在book表)app

models.Book.objects.create(title='三國演義',price=200,publish_id=1)  #publish_id是mysql數據庫中顯示的字段名

publish直接傳出版社對象    (publish是models.py設計表字段名)es5

#查詢到的publish表主鍵爲2的對象
publish_obj = models.Publish.objects.filter(pk=2).first()

models.Book.objects.create(title='紅樓夢',price=250,publish=publish_obj)  #publish是models.py中的字段名

改    updatespa

傳數字的設計

models.Book.objects.filter(pk=2).update(publish_id=3)  #修改publish_id=3

傳對象的code

#查詢publish表中要修改的對象主鍵值爲2
publish_obj = models.Publish.objects.filter(pk=2).first()
#修改
models.Book.objects.filter(pk=1).update(publish=publish_obj)   #把pk=1的數據publish字段更換

刪  delete對象

models.Publish.objects.filter(pk=2).delete()  # 默認都是級聯更新 級聯刪除

多對多字段的增刪改(book表和author表是多對多關係,新生成一張表)

增   add()

要給主鍵爲1的書籍添加兩個做者

傳數字
#先查詢主鍵爲1的書籍 book_obj = models.Book.objects.filter(pk=1).first() print(book_obj.book_author) 這個book_author是book表中多對多虛擬字段,book_author是字段名 #對象點擊多對多虛擬字段,會直接跨到多對多的第三張表 book_obj.book_author.add(1) 傳數字 給書籍1增長主鍵爲1的做者 book_obj.book_author.add(2,3) 一次性給書籍1增長主鍵爲2,3的做者
傳對象 author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=2).first() author_obj2 = models.Author.objects.filter(pk=3).first() book_obj.book_author.add(author_obj) 傳對象 book_obj.book_author.add(author_obj1,author_obj2) add() 是給書籍添加做者 括號內既能夠傳數字也能夠傳對象,可是不要混着用 而且支持一次性傳多個 逗號隔開便可

多對多表(mysql)

 

 改  set()     

將主鍵爲1的書籍對象做者修改成2,3

傳數字
#也是先查詢出主鍵爲1的書籍 book_obj = models.Book.objects.filter(pk=1).first() book_obj.book_author.set([2,]) book_obj.book_author.set([2,3])

傳對象
author_obj = models.Author.objects.filter(pk=1).first()
author_obj1 = models.Author.objects.filter(pk=2).first()
author_obj2 = models.Author.objects.filter(pk=3).first()
book_obj.book_author.set([author_obj,])
book_obj.book_author.set([author_obj, author_obj1, author_obj2])
注意:set()括號內 傳一個可迭代對象 (******)
可迭代對象中 能夠是多個數字組合
也能夠是多個對象組合
可是不要混着用!!!

上一步主鍵爲1的書籍綁定了三個做者,如今改成兩個,就是把多餘的刪除掉

 刪    remove()

刪除主鍵值爲1的書籍做者2

傳數字
#也是先查詢出主鍵爲1的書籍
book_obj = models.Book.objects.filter(pk=1).first() book_obj.book_author.remove(2) book_obj.book_author.remove(2,3) 傳對象 author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=2).first() author_obj2 = models.Author.objects.filter(pk=3).first() book_obj.book_author.remove(author_obj) book_obj.book_author.remove(author_obj1,author_obj2)

remove()括號內既能夠傳數字 也能夠傳對象 
而且支持傳對個 逗號隔開便可

刪除做者2

 清空  clear()

 將某本書跟做者的關係所有清空

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.book_author.clear()  # 清空當前書籍與做者的全部關係

多對多增刪改總結(******)

add()
set()
remove()
上面三個都支持傳數字 或者對象 而且能夠傳多個 可是set須要傳可迭代對象
    
clear()
clear括號內不須要傳任何參數

2、跨表查詢(******)  就是前面缺的查詢

正向與反向的概念

一對一
正向:author---關聯字段在author表裏--->authordetail 按字段 反向:authordetail---關聯字段在author表裏--->author 按表名小寫 一對多 正向:book---關聯字段在book表裏--->publish 按字段,查詢多個對象.all() 反向:publish---關聯字段在book表裏--->book 按表名小寫,查詢多個對象_set.all() 多對多 正向:book---關聯字段在book表裏--->author 按字段,查詢多個對象.all() 反向:author---關聯字段在book表裏--->book 按表名小寫,查詢多個對象_set.all() 正向查詢按外鍵字段 反向查詢按表名小寫

基於對象的跨表查詢(子查詢:將一張表的查詢結果當作另外一個查詢語句的條件)

1.查詢書籍id是1的出版社名稱   (一對多查詢)正向查詢

先查詢出id爲1的書籍對象
book_obj = models.Book.objects.filter(pk=1).first() print(book_obj.publish.name) #正向查詢,由於publish在book表中,直接對象.字段名就能獲取到 print(book_obj.publish.addr)

2.查詢書籍id是2的做者姓名   (多對多查詢) 正向查詢

先查詢出書籍id爲2的對象
book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.book_author) #正向查詢 #app01.Author.None print(book_obj.book_author.all()) #<QuerySet [<Author: jason>, <Author: egon>]> res =book_obj.book_author.all() for r in res: print(r.name) #jason egon

3.查詢做者是jason的家庭住址  (一對一查詢)正向查詢

#先查做者名的jason的對象
author_obj = models.Author.objects.filter(name='jason').first()

print(author_obj.author_detail.addr) #正向查詢  在Author表中有author_detil字段

4.查詢出版社是東方出版社出版的書籍  (一對多查詢)反向查詢

#先查詢出出版社是東方出版社的對象
publish_obj = models.Publish.objects.filter(name='東方出版社').first()
print(publish_obj.book_set.all())  #<QuerySet [<Book: 三國演義>, <Book: 西遊記>]>   #須要加.all()才能獲取到結果
 res = publish_obj.book_set.all() for r in res: print(r.title) #三國演義 西遊記

5.查詢做者是jason的寫過的全部的書籍   (多對多查詢)反向查詢

#先查詢做者是jason的對象
author_obj = models.Author.objects.filter(name='jason').first()

print(author_obj.book_set)  # app01.Book.None
print(author_obj.book_set.all())  #<QuerySet [<Book: 三國演義>, <Book: 紅樓夢>]>

res=author_obj.book_set.all()
  for r in res:
    print(r.title)

6.查詢電話號碼是130的做者姓名  (一對一查詢)反向查詢

#先查詢電話號碼是130的對象
author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()

print(author_detail_obj.author.name) #反向查詢 print(author_detail_obj.author.addr)

須要注意:正向查詢多個的時候,須要加.all()    在反向查詢的結果是多個的時候,須要加_set.all()  (******)

7.查詢書籍id爲1的做者的電話號碼  (多對多查詢)正向查詢

book_obj = models.Book.objects.filter(pk=1).first()
author_list = book_obj.book_author.all() #多個結果時候用all() for author_obj in author_list: print(author_obj.author_detail.phone) 直接.就能出結果

基於雙下劃線的跨表查詢(連表操做)

-正向:按字段,跨表能夠在filter,也能夠在values中
-反向:按表名小寫,跨表能夠在filter,也能夠在values中

1.查詢jason做者的手機號  (一對一查詢)正向查詢

models.Author.objects.filter(name='jason').values('author_detail__phone')   #author_detail是Author的字段(因此是正向查詢)

2.查詢jason做者的手機號    反向查詢

models.AuthorDetail.objects.filter(author__name='jason').values('phone')  #反向查詢  author是小寫表名

3.查詢jason這個做者的年齡和手機號  (一對一查詢)正向查詢

models.Author.objects.filter(name='jason').values('age','author_detail__phone')

4.查詢jason這個做者的年齡和手機號  反向查詢

models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')

5.查詢手機號是130的做者年齡    (一對一查詢)正向查詢

models.Author.objects.filter(author_detail__phone=130).values('age')

6.查詢手機號是130的做者年齡    反向查詢

models.AuthorDetail.objects.filter(phone=130).values('author__age')

7.查詢書籍id是1的做者的電話號碼

models.Book.objects.filter(pk=1).values('book_author__author_detail__phone')
models.Book.objects.filter(pk=1).values('外鍵字段1__外鍵字段2__普通字段')
只要表裏面有外鍵字段 你就能夠無限制跨多張表

 

1.查詢出版社爲北京出版社的全部圖書的名字和價格  (一對多查詢)正向

models.Book.objects(publish__name='北京出版社').values('title','price')

2.查詢出版社爲北京出版社的全部圖書的名字和價格  (一對多查詢)反向

models.Publish.objects.filter(name='北京出版社').values('book__name','book__price')

3.查詢北京出版社出版的價格大於19的書

models.Book.objects.filter(price__gt=19,publish__name='北京出版社').values('title')

3、聚合查詢(aggregate)

from django.db.models import Max,Min,Count,Avg,Sum   #查詢總和,平均,最大,最小

res = models.Book.objects.aggregate(Sum('price')) res1 = models.Book.objects.aggregate(Avg('price')) res2 = models.Book.objects.aggregate(Count('price')) res3 = models.Book.objects.aggregate(Max('price')) res4 = models.Book.objects.aggregate(Min('price')) res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price')) #也能夠放在一個裏面寫

4、分組查詢 (annotate)

 1.統計每一本書的做者個數

from django.db.models import Max, Min, Count, Avg, Sum
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
 #book表根據authors分組求和,author_num是取的別名,values是控制檯打印的值

2.統計每一個出版社賣的最便宜的書的價格

res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')

3.統計不止一個做者的圖書

res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)

4.查詢每一個做者出的書的總價格

res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')

5、F查詢與Q查詢

 F查詢的本質就是從數據庫中獲取某個字段的值,以前查詢等號後面的條件都是咱們人爲輸入的,如今變成了須要從數據庫中獲取數據放在等號後面

查詢庫存量大於賣出量的書籍

from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu')) #kucun和maichu都是Book表的字段

將書籍庫存數所有增長1000

models.Book.objects.update(kucun=F('kucun')+1000)

把全部書名後面加上'新款'    (注意修改char類型的字段不能按照上面那種方式,須要使用Concat,加上拼接值value)

from django.db.models.functions import Concat
from django.db.models import Value ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款'))) models.Book.objects.update(title = F('title')+'新款') # 不能這麼寫

Q查詢  (filter裏面條件都是與,Q支持與或非)

 查詢書籍名稱是三國演義或者價格是444

from django.db.models import Q
res = models.Book.objects.filter(title='三國演義',price=444.44)  # filter只支持and關係
res1 = models.Book.objects.filter(Q(title='三國演義'),Q(price=444))  # 若是用逗號 那麼仍是and關係
res2 = models.Book.objects.filter(Q(title='三國演義')|Q(price=444)) #或者關係 res3 = models.Book.objects.filter(~Q(title='三國演義')|Q(price=444)) #查詢除了title是三國演義,或者價格是444的書籍

Q的高級用法

from django.db.models import Q
q = Q() q.connector = 'or' # 修改查詢條件的關係 默認是and q.children.append(('title__contains','三國演義')) # 往列表中添加篩選條件 q.children.append(('price__gt',444)) # 往列表中添加篩選條件 res = models.Book.objects.filter(q) # filter支持你直接傳q對象 可是默認仍是and關係 print(res)
相關文章
相關標籤/搜索