1. 程式人生 > 其它 >Django外來鍵欄位 多表查詢

Django外來鍵欄位 多表查詢

神奇的雙下劃線查詢

res = models.User.objects.filter(age__gt=20)  # 查詢年齡大於20的使用者
res = models.User.objects.filter(age__lt=20)  # 查詢年齡小於20的使用者
    '''
        __gt    大於
        __lt    小於
        __gte   大於等於
        __lte   小於等於
    '''

res = models.User.objects.filter(age__in=[18, 22, 25])  # 成員運算  查詢年齡是18,22,25的使用者4
res = models.User.objects.filter(age__range=[18, 16]) # 查詢年齡在18到26之間的使用者 包含18和26 ''' __range 範圍查詢 ''' res = models.User.objects.filter(name__contains='J') # 查詢姓名中包含字母j的使用者 res = models.User.objects.filter(name__icontains='J') ''' __contains 區分大小寫 __icontains 忽略大小寫
''' res = models.User.objects.filter(op_time__month=5) # 查詢月份是5月的資料使用者 res = models.User.objects.filter(op_time__year=2022) # 查詢年份是2022年的資料使用者 ''' __year 按照年份篩選資料 __month 按照月份篩選資料 '''

外來鍵欄位的建立

"""
MySQL複習
關係的種類
    一對多關係
    多對多關係
    一對一關係
關係的判斷
    換位思考
欄位的位置
    一對多關係 外來鍵欄位建在多的一方
    多對多關係 外來鍵欄位建在第三張關係表中
    一對一關係 外來鍵欄位建在任意一方都可以 但是推薦建在查詢頻率較高的表中
""" django orm建立表關係 圖書表 出版社表 作者表 作者詳情表 關係判斷 書與出版社 一本書不能對應多個出版社 一個出版社可以對應多本書 # 一對多關係 書是多 出版社是一 ForeignKey '''django orm外來鍵欄位針對一對多關係也是建在多的一方 ''' 書與作者 一本書可以對應多個作者 一個作者可以對應多本書 # 多對多關係 ManyToManyField '''django orm外來鍵欄位針對多對多關係 可以不用自己建立第三張表''' 作者與作者詳情 一個作者不能對應多個作者詳情 一個作者詳情不能對個多個作者 # 一對一關係 OneToOneField '''django orm外來鍵欄位針對一對一關係 建在查詢頻率較高的表中''' ManyToManyField不會在表中建立實際的欄位 而是告訴django orm自動建立第三張關係表 ForeignKey、OneToOneField會在欄位的後面自動新增_id字尾 如果你在定義模型類的時候自己添加了該字尾那麼遷移的時候還會再次新增_id_id 所以不要自己加_id字尾 ps:三個關鍵字裡面的引數 to用於指定跟哪張表有關係 自動關聯主鍵 to_field\to_fields 也可以自己指定關聯欄位

外來鍵欄位操作

# 一對多、一對一外來鍵欄位操作
  增
    publish_id=1             author_detail_id=1
    publish=publish_obj      author_detail=detail_obj
  改
    update(publish_id=3)         update(author_detail_id=3)
    update(publish=publish_obj)  update(author_detail=detail_obj)
 
# 多對多欄位操作
  1.第三張關係表建立資料
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.add()
        括號內可以放主鍵值也可以放資料物件 並且都支援多個
  2.第三張關係表修改資料
      book_obj.authors.set()
        括號內必須是一個可迭代物件 元素同樣支援主鍵值或者資料物件
  3.第三張關係表刪除資料
      book_obj.authors.remove()
        括號內可以放主鍵值也可以放資料物件 並且都支援多個
  4.第三張關係表清空指定資料
      book_obj.authors.clear()
        括號內無需傳值 直接清空當前表在第三張關係表中的繫結記錄

多表查詢

"""
MySQL多表查詢思路
    子查詢
        將SQL語句用括號括起來當做條件使用
    連表操作
        inner join\left join\right join\union
        django orm本質還是使用的上述兩種方法
    子查詢>>>:基於物件的跨表查詢
    連表操作>>>:基於雙下劃線的跨表查詢
"""
# 正反向的概念
    核心在於當前資料物件是否含有外來鍵欄位 有則是正向 沒有則是反向
    正向
      eg:
        由書籍查詢出版社 外來鍵欄位在書籍表中 那麼書查出版社就是'正向'
        由書籍查詢作者 外來鍵欄位在書籍表中 那麼書查作者就是'正向'
        由作者查詢作者詳情 外來鍵欄位在作者表中 那麼也是'正向'
    反向
      eg:
        由出版社查詢書籍 外來鍵欄位不在出版社表 那麼出版社查書就是'反向'
      ...
     """
     查詢口訣
         正向查詢按外來鍵欄位名
         反向查詢按表名小寫
     """

# 編寫orm跟編寫SQL語句一樣 不要總想著一步到位!!!

基於物件的跨表查詢

"""基於物件的跨表查詢本質就是子查詢即分步操作即可"""
    # 1.查詢資料分析書籍對應的出版社
    # 先獲取書籍物件
book_obj = models.Book.objects.filter(title='資料分析').first()
    # 再使用跨表查詢
res = book_obj.publish
print(res)  # 出版社物件:北方出版社
    # 2.查詢python全棧開發對應的作者
    # 先獲取書籍物件
book_obj = models.Book.objects.filter(title='python全棧開發').first()
    # 再使用跨表查詢
res = book_obj.authors  # app01.Author.None
res = book_obj.authors.all()
print(res)  # <QuerySet [<Author: 作者物件:jason>, <Author: 作者物件:jerry>]>
    # 3.查詢作者jason的詳情資訊
    # 先獲取jason作者物件
author_obj = models.Author.objects.filter(name='jason').first()
    # 再使用跨表查詢
res = author_obj.author_detail
print(res)  # 作者詳情物件:蕪湖

    # 4.查詢東方出版社出版的書籍
publish_obj = models.Publish.objects.filter(name='東方出版社').first()
res = publish_obj.book_set  # app01.Book.None
res = publish_obj.book_set.all()
print(res)  # <QuerySet [<Book: 書籍物件:linux雲端計算>, <Book: 書籍物件:聊齋志異>]>
    # 5.查詢jason編寫的書籍
author_obj = models.Author.objects.filter(name='jason').first()
res = author_obj.book_set  # app01.Book.None
res = author_obj.book_set.all()
print(res)  # <QuerySet [<Book: 書籍物件:golang高併發>, <Book: 書籍物件:python全棧開發>]>
    # 6.查詢電話是110的作者
    author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    res = author_detail_obj.author
    print(res)  # 作者物件:jason

基於雙下劃線的跨表查詢

"""基於雙下劃線的跨表查詢本質就是連表操作"""
# 基於雙下劃線的跨表查詢
    """
    查詢資料分析書籍對應的價格和出版日期
    models.Book.objects.filter(title='資料分析').values('price','publish_time')
    """
    '''手上有什麼條件就先拿models點該條件對應的表名'''
    # 1.查詢資料分析書籍對應的出版社名稱
res = models.Book.objects.filter(title='資料分析').values('publish__name', 'publish__addr')
print(res)  # <QuerySet [{'publish__name': '北方出版社', 'publish__addr': '北京'}]>
    # 2.查詢python全棧開發對應的作者姓名和年齡
res = models.Book.objects.filter(title='python全棧開發').values('authors__name','authors__age')
print(res)  # <QuerySet [{'authors__name': 'jason', 'authors__age': 18}, {'authors__name': 'jerry', 'authors__age': 29}]>
    # 3.查詢作者jason的手機號和地址
res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
print(res)  # <QuerySet [{'author_detail__phone': 110, 'author_detail__addr': '蕪湖'}]>

    # 4.查詢東方出版社出版的書籍名稱和價格
res = models.Publish.objects.filter(name='東方出版社').values('book__title','book__price')
print(res)  # <QuerySet [{'book__title': 'linux雲端計算', 'book__price': Decimal('24888.44')}, {'book__title': '聊齋志異', 'book__price': Decimal('16987.22')}]>
    # 5.查詢jason編寫的書籍名稱和日期
res = models.Author.objects.filter(name='jason').values('book__title', 'book__publish_time')
print(res)  # <QuerySet [{'book__title': 'golang高併發', 'book__publish_time': datetime.date(2022, 6, 7)}, {'book__title': 'python全棧開發', 'book__publish_time': datetime.date(2022, 2, 28)}]>
    # 6.查詢電話是110的作者的姓名和年齡
res = models.AuthorDetail.objects.filter(phone=110).values('author__name','author__age')
print(res)  # <QuerySet [{'author__name': 'jason', 'author__age': 18}]>

雙下線查詢擴充套件

"""基於雙下劃線的跨表查詢的結果也可以是完整的資料物件"""

'''手上有條件所在的表可以不被models點 直接點最終的目標資料對應的表'''
    # 1.查詢資料分析書籍對應的出版社名稱
res = models.Publish.objects.filter(book__title='資料分析')
print(res)  # <QuerySet [<Publish: 出版社物件:北方出版社>]>
res = models.Publish.objects.filter(book__title='資料分析').values('name')
print(res)  # <QuerySet [{'name': '北方出版社'}]>
    # 2.查詢python全棧開發對應的作者姓名和年齡
res = models.Author.objects.filter(book__title='python全棧開發').values('name','age')
print(res)  # <QuerySet [{'name': 'jason', 'age': 18}, {'name': 'jerry', 'age': 29}]>
    # 3.查詢作者jason的手機號和地址
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','addr')
print(res)  # <QuerySet [{'phone': 110, 'addr': '蕪湖'}]>
    # 4.查詢東方出版社出版的書籍名稱和價格
res = models.Book.objects.filter(publish__name='東方出版社').values('title','price')
print(res)  # <QuerySet [{'title': 'linux雲端計算', 'price': Decimal('24888.44')}, {'title': '聊齋志異', 'price': Decimal('16987.22')}]>
    # 5.查詢jason編寫的書籍名稱和日期
res = models.Book.objects.filter(authors__name='jason').values('title','publish_time')
print(res)  # <QuerySet [{'title': 'golang高併發', 'publish_time': datetime.date(2022, 6, 7)}, {'title': 'python全棧開發', 'publish_time': datetime.date(2022, 2, 28)}]>
    # 6.查詢電話是110的作者的姓名和年齡
res = models.Author.objects.filter(author_detail__phone=110).values('name','age')
print(res)  # <QuerySet [{'name': 'jason', 'age': 18}]>
 


# 連續跨表操作
# 查詢python全棧開發對應的作者的手機號res = models.Book.objects.filter(title='python全棧開發').values('authors__author_detail__phone')print(res)  # <QuerySet [{'authors__author_detail__phone': 110}, {'authors__author_detail__phone': 140}]>
res1 = models.AuthorDetail.objects.filter(author__book__title='python全棧開發').values('phone')
print(res1)  # <QuerySet [{'phone': 110}, {'phone': 140}]>


"""
可能出現的不是疑問的疑問:如何獲取多張表裡面的欄位資料
res = models.Book.objects.filter(title='python全棧開發').values('authors__author_detail__phone','authors__name','title')
print(res)
"""

如何檢視SQL語句

方式1:如果結果集物件是queryset 那麼可以直接點query檢視
方式2:配置檔案固定配置
     適用面更廣 只要執行了orm操作 都會列印內部SQL語句