Django 多表、跨表、聚合、分組查詢

前期準備:git

建立表sql

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_time = models.DateField(auto_now_add=True)  #該字段新增數據會自動添加實時時間

    #出版社 一對多 外鍵字段建在多的一方
    publish = models.ForeignKey(to='Publish')
    #做者 多對多 外鍵字段推薦建在查詢頻率較高的表
    authors = models.ManyToManyField(to='Author')

class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64)

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()

    #做者詳情 一對一  外鍵字段推薦建在查詢頻率較高的表
    author_detail = models.OneToOneField(to='AuthorDetail')

class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=32)
View Code

Django多表查詢

外鍵字段的增刪改查

外鍵字段在1.X版本中默認就是級聯更新級聯刪除
2.X版本中則須要手動指定(百度)django

一對多 publish

增:app

# 增 方式1 直接寫實際的表字段 publish_id
models.Book.objects.create(title='三國',price='123.12',publish_id=2)
# 增 方式2
publish_obj = models.Publish.objects.get(pk=1)
models.Book.objects.create(title='水滸傳',price=66,publish=publish_obj)

改:ide

# 改 方式1
models.Book.objects.filter(pk=1).update(publish_id=3)
# 改 方式2
publish_obj = models.Publish.objects.get(pk=4)
models.Book.objects.filter(pk=1).update(publish=publish_obj)

多對多

add:spa

#1.給書籍和做者綁定關係 add

"""
add專門給第三張關係表添加數據
    括號內便可以傳數字也能夠傳對象  而且都支持傳多個
"""

book_obj = models.Book.objects.filter(pk=1).first()
# 書籍和做者的關係是由第三張表決定  也就意味着你須要操做第三張表
# 書籍對象點虛擬字段authors就相似於已經跨到書籍和做者的第三張關係表中
# print(book_obj.authors)  #app01.Author.None

# 方式一
book_obj.authors.add(1)  #給書籍綁定一個主鍵爲1的做者
book_obj.authors.add(2,3)

# 方式二
author_obj = models.Author.objects.get(pk=2) 
author_obj1 = models.Author.objects.get(pk=3) 
book_obj.authors.add(author_obj) 
book_obj.authors.add(author_obj,author_obj1)

remove:code

# 2.移除書籍與做者的綁定關係 remove

"""
remove專門給第三張關係表移除數據
    括號內便可以傳數字也能夠傳對象  而且都支持傳多個
"""

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(2)
book_obj.authors.remove(1,3)

# author_obj = models.Author.objects.get(pk=2)
# author_obj1 = models.Author.objects.get(pk=3)
# book_obj.authors.remove(author_obj)
# book_obj.authors.remove(author_obj,author_obj1)

set:orm

# 3 修改書籍與做者的關係   set

"""
set 修改書籍與做者的關係
    括號內支持傳數字和對象 可是須要是可迭代對象
"""

book_obj = models.Book.objects.filter(pk=1).first()
# book_obj.authors.set((3,))
book_obj.authors.set((2, 3))

author_obj = models.Author.objects.get(pk=2)
author_obj1 = models.Author.objects.get(pk=3)
book_obj.authors.set((author_obj,))
book_obj.authors.set([author_obj,author_obj1])

clear:對象

# 4 清空書籍與做者關係

"""
clear()  清空關係
不須要任何的參數
"""

book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()  # 去第三張表中清空書籍爲1的全部數據

Django 跨表查詢

跨表查詢的方式
  1.子查詢 將一張表的查詢結果當作另一張表的查詢條件
  2.鏈表查詢 

建議:在寫sql語句或者orm語句的時候,千萬不要想着一次性將語句寫完,必定要寫一點查一點blog

 

正反向的概念
  正向
    跨表查詢的時候,看外鍵字段是否在當前數據對象中,若是在的話,查詢另一張關係表 叫正向
    
  反向
    若是不在叫反向

口訣
  正向查詢按外鍵字段
  反向查詢按表名小寫 看狀況加_set

基於對象的跨表查詢(子查詢)

#正向:

# 1.查詢書籍pk爲1的出版社名稱
book_obj = models.Book.objects.filter(pk=1).first() #先拿到書籍對象
print(book_obj.publish)  #書籍對象點外鍵字段拿到的是出版社對象
print(book_obj.publish.name)
print(book_obj.publish.addr)

# 2.查詢書籍pk爲2的全部做者的姓名
book_obj = models.Book.objects.filter(pk=2).first()
# print(book_obj.authors)  # app01.Author.None
print(book_obj.authors.all())  #<QuerySet [<Author: Author object>]>
author_list = book_obj.authors.all()
for author_obj in author_list:
    print(author_obj.name)

# 3.查詢做者hank的電話號碼
author_obj = models.Author.objects.filter(name='hank').first()
print(author_obj.author_detail)
print(author_obj.author_detail.phone)

"""
    正向查詢的時候 當外鍵字段對應的數據能夠有多個的時候須要加.all()
    不然點外鍵字典便可獲取到對應的數據對象
"""

#反向

# 3.查詢做者hank的電話號碼
author_obj = models.Author.objects.filter(name='hank').first()
print(author_obj.author_detail)
print(author_obj.author_detail.phone)

# 4.查詢出版社名稱爲東方出版社出版過的書籍
publish_obj = models.Publish.objects.filter(name='東方出版社').first()
print(publish_obj.book_set)  #app01.Book.None
print(publish_obj.book_set.all()) #<QuerySet [<Book: Book object>]>

# 5.查詢做者hank寫過的書
author_obj = models.Author.objects.filter(name='hank').first()
print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all())

# 6.查詢手機號爲120的做者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first()
print(author_detail_obj.author.name)

"""
    基於對象的反向查詢 表名小寫是否須要加_set.all()?
        一對多和多對多的時候須要加
        一對一不須要  
"""

基於雙下劃線跨表查詢(鏈表查詢)

注意:只要表之間有關係,你就能夠經過正向的外鍵字段或者反向的表名小寫,連續跨表操做

# 1.查詢書籍pk爲1的出版社名稱
# 正向
res = models.Book.objects.filter(pk=1).values('publish__name')  # 寫外鍵字段 就意味着你已經在外鍵字段管理的那張表中
print(res)  #<QuerySet [{'publish__name': '西方出版社'}]>
# 反向
res = models.Publish.objects.filter(book__pk=1).first() # 拿出版過pk爲1的書籍對應的出版社
print(res.name)  #西方出版社

# 2.查詢書籍pk爲1的做者姓名和年齡
# 正向
res = models.Book.objects.filter(pk=1).values('title','authors__name','authors__age')
print(res)
# 反向
# res = models.Author.objects.filter(book__pk=1)  # 拿出出版過書籍pk爲1的做者
res = models.Author.objects.filter(book__pk=1).values('name','age')
print(res)

# 3.查詢做者是hank的年齡和手機號
# 正向
res = models.Author.objects.filter(name='hank').values('age','author_detail__phone')
print(res)
# 反向
# res = models.AuthorDetail.objects.filter(author__name='hank') #拿到hank的我的詳情
res = models.AuthorDetail.objects.filter(author__name='hank').values('phone','author__age')
print(res)

# 4.查詢書籍pk爲的1的做者的手機號
# 正向
res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
print(res)   #<QuerySet [{'authors__author_detail__phone': 120}]>
# 反向
res = models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
print(res)  #<QuerySet [{'phone': 120}]>

聚合查詢

關鍵字:aggregate

from django.db.models import Max,Min,Avg,Count,Sum
# 查詢全部書的平均價格 res = models.Book.objects.aggregate(Avg('price')) print(res) # 查詢價格最貴的書 res = models.Book.objects.aggregate(Max('price')) print(res) #查詢書的總數 res = models.Book.objects.aggregate(Count("pk")) print(res) # 查詢全部書的總價 res = models.Book.objects.aggregate(Sum('price')) print(res)

分組查詢

關鍵字:annotate

# 1.統計每一本書的做者個數
res = models.Book.objects.annotate(author_num=Count('authors')).values('title','author_num')
print(res)

# 2.統計出每一個出版社賣的最便宜的書的價格
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price','book__title')
print(res)

# 3.統計不止一個做者的圖書
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title')
print(res)

# 4.查詢各個做者出的書的總價格
res = models.Author.objects.annotate(price_sum=Sum('book__price')).values('name','price_sum')
print(res)

# 5.如何按照表中的某一個指定字段分組
"""
res = models.Book.objects.values('price').annotate()  就是以價格分組
"""
相關文章
相關標籤/搜索