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


前期准備:

創建表

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版本中則需要手動指定(百度)

一對多 publish

增:

# 增 方式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)

改:

# 改 方式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:

#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:

# 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:

# 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語句的時候,千萬不要想着一次性將語句寫完,一定要寫一點查一點

 

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

口訣
  正向查詢按外鍵字段
  反向查詢按表名小寫 看情況加_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()
    否則點外鍵字段即可獲取到對應的數據對象
"""

#反向# 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

'''
models后面點什么表名,后面如果直接跟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) #如何按照表中的某一個指定字段分組 """ res = models.Book.objects.values('price').annotate() 就是以價格分組 """


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM