Django?ORM?多表查詢(xún)示例代碼
數(shù)據(jù)準(zhǔn)備
moduls.py
# 構(gòu)建表結(jié)構(gòu)
from django.db import models
# 表app01_publish
class Publish(models.Model):
name = models.CharField(max_length=20)
addr = models.CharField(max_length=20)
# 表app01_author_detail
class Author_Detail(models.Model):
tel = models.CharField(max_length=20)
# 表app01_author
class Author(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
# 表app01_author一對(duì)一表app01_authordetail
detail = models.OneToOneField(to='Author_Detail',to_field='id',unique=True,on_delete=models.CASCADE)
# 表app01_book
class Book(models.Model):
title = models.CharField(max_length=20)
price = models.DecimalField(max_digits=8, decimal_places=2)
pub_date = models.DateField(auto_now_add=True)
# 表app01_book多對(duì)一表app01_publish,參數(shù)to指定模型名,參數(shù)to_field指定要關(guān)聯(lián)的那個(gè)字段
publish = models.ForeignKey(to='Publish',to_field='id',on_delete=models.CASCADE)
# 我們自己寫(xiě)sql時(shí),針對(duì)書(shū)籍表與作者表的多對(duì)關(guān)系,需要自己創(chuàng)建新表,而基于django的orm,下面這一行代碼可以幫我們自動(dòng)創(chuàng)建那張關(guān)系表
authors=models.ManyToManyField(to='Author')
# 變量名為authors,則新表名為app01_book_authors,若變量名為xxx,則新表名為app01_book_xxx
tests.py
# 添加數(shù)據(jù)
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "book_sys.settings")
import django
django.setup()
from app01.models import *
# 1、先添加沒(méi)有外鍵字段的 author_detail表 pubulish表
Author_Detail.objects.create(tel='123456789')
Author_Detail.objects.create(tel='987654321')
Author_Detail.objects.create(tel='000000000')
Publish.objects.create(name='北方出版社',addr='北京')
Publish.objects.create(name='南方出版社',addr='南京')
Publish.objects.create(name='東方出版社',addr='上海')
Publish.objects.create(name='西方出版社',addr='西安')
# 2、添加 author表 book表
Author.objects.create(name='frank',age=31 ,detail_id=1)
Author.objects.create(name='lili',age=29 ,detail_id=2)
Author.objects.create(name='tank',age=42 ,detail_id=3)
Book.objects.create(title='三國(guó)演義',price=200 ,publish_id=1)
Book.objects.create(title='三國(guó)志',price=198.5 ,publish_id=2)
Book.objects.create(title='紅樓夢(mèng)',price=255.43 ,publish_id=2)
Book.objects.create(title='西游記',price=300.5 ,publish_id=3)
Book.objects.create(title='西廂記',price=213.4 ,publish_id=4)
Book.objects.create(title='水滸傳',price=199 ,publish_id=1)
# 3、最后操作 author_book表,由于使用的是 ManyToMany 字段自動(dòng)生成的,所以要基于外鍵所在的表進(jìn)行操作
book_obj1=Book.objects.filter(pk=1).first()
book_obj1.authors.add(1,2)
book_obj2 = Book.objects.filter(pk=2).first()
book_obj2.authors.add(1)
book_obj3 = Book.objects.filter(pk=3).first()
author_obj1 = Author.objects.filter(pk=1).first()
author_obj2 = Author.objects.filter(pk=2).first()
book_obj3.authors.add(author_obj1,author_obj2)
book_obj4 = Book.objects.filter(pk=4).first()
book_obj4.authors.add(3,2)
book_obj5 = Book.objects.filter(pk=5).first()
book_obj5.authors.add(3)
book_obj6 = Book.objects.filter(pk=6).first()
book_obj6.authors.add(1,3)正向查詢(xún)與反向查詢(xún)
一出版社和書(shū)籍為例, 書(shū)記表含有出版社表的外鍵字段
正向查詢(xún)>>> 書(shū)籍查詢(xún)出版社
反向查詢(xún)>>> 出版社查詢(xún)書(shū)籍
總結(jié): 當(dāng)前查詢(xún)對(duì)象是否含有外鍵字段, 有就是正向查詢(xún), 沒(méi)有就是反向查詢(xún)
正向查詢(xún)按照字段查詢(xún), 反向查詢(xún)按照表名查詢(xún)
基于對(duì)象的跨表查詢(xún)
相當(dāng)于MySQL中的子查詢(xún): 將一張表的查詢(xún)結(jié)果用括號(hào)括起來(lái), 當(dāng)作另一條SQL語(yǔ)句的條件 .
正向查詢(xún)
一對(duì)多
查詢(xún)書(shū)籍主鍵為5 的出版社名稱(chēng)
1. 查主鍵為5的書(shū)籍對(duì)象
2. 根據(jù)書(shū)籍對(duì)象的外鍵字段 publish 獲取到出版社對(duì)象
3. 由出版社對(duì)象獲取到名稱(chēng)
book_obj = Book.objects.filter(pk=5).first() res = book_obj.publish print(res) # Publish object print(res.name) # 西方出版社
多對(duì)多
查詢(xún)書(shū)籍主鍵為3的作者姓名
1. 查詢(xún)書(shū)籍主鍵為3的書(shū)籍對(duì)象
2. 外鍵字段在書(shū)籍表中, 同樣是正向查詢(xún),那么只需要按照字段autjors查詢(xún)即可
3. 獲取作者對(duì)象的姓名
book_obj = Book.objects.filter(pk=3).first() res = book_obj.authors print(res) # app01.Author.None
注意: 由于字段authors 是多對(duì)多的外鍵字段, 此時(shí)拿到的對(duì)象還需要進(jìn)一步的操作
book_obj = Book.objects.filter(pk=3).first() res = book_obj.authors res1 = book_obj.authors.all() print(res1) # <QuerySet [<Author: Author object>, <Author: Author object>]>
然后再for循環(huán)各自的姓名即可
一對(duì)一
查詢(xún)作者lili的號(hào)碼
1.查詢(xún)作者對(duì)象
2,外鍵字段再作者表中, 同樣是正向查詢(xún),那么只需要按照字典detail查詢(xún)即可
3. 獲取詳情對(duì)象的tel
author_obj = Author.objects.filter(name='lili').first() res = author_obj.detail print(res) print(res.tel)
反向查詢(xún) 一對(duì)多
查詢(xún)東方出版社出版的書(shū)籍
1. 先獲取東方出版社的對(duì)象
2. 出版社沒(méi)有外鍵字段, 去查書(shū)籍是反向查詢(xún)
3. 表名小寫(xiě)_set.all()
4. 獲取書(shū)籍名稱(chēng)
publish_obj=Publish.objects.filter(name='東方出版社').first() print(publish_obj) # Publish object res = publish_obj.book_set print(res) # app01.Book.None res1 = res.all() print(res1) # <QuerySet [<Book: Book object>]> for obj in res1: print(obj.title)
多對(duì)多
查詢(xún)作者lili寫(xiě)過(guò)的書(shū)籍
1.獲取作者對(duì)象
2. 作者表中沒(méi)有書(shū)籍表的外鍵, 所以是反向查詢(xún)
3. .book_set.all()獲取書(shū)籍對(duì)象
4. 再獲取書(shū)籍對(duì)象的名稱(chēng)
author_obj = Author.objects.filter(name='lili').first() res = author_obj.book_set print(res) # app01.Book.None res1 = res.all() print(res1) # <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]> for obj in res1: print(obj.title, end='') # 三國(guó)演義,紅樓夢(mèng),西游記,
一對(duì)一
查詢(xún)號(hào)碼為0000000的作者
1. 查詢(xún)作者對(duì)象詳情
2.外鍵字段在作者表中, 同樣是證詞昂查詢(xún), 那么只需要按照字段detail 查詢(xún)即可
3. 獲取詳情對(duì)象的tel
detail_obj = Author_Detail.objects.filter(tel='000000000').first() print(detail_obj) # Author_Detail object res = detail_obj.author print(res) # Author object print(res.name) # tank
方法總結(jié)
正向查詢(xún)
一對(duì)一, 一對(duì)多的方法是一樣的, 按照字段查詢(xún)就能夠直接找到對(duì)象 --- author_obj.detail
一對(duì)多 , 按照字段查詢(xún)后會(huì)返回一個(gè).None的對(duì)象, 需要在字段后面加上.all()>>> book_obj.authors.all()
反向查詢(xún)
一對(duì)多,多對(duì)多的方法是一樣的, 按照表名小寫(xiě), 在跟上_set.all()>>>author_obj.book_set.all()
一對(duì)一, 則直接按照表明小寫(xiě), 能夠直接拿到>> > detail_obj.author
當(dāng)查詢(xún)到的結(jié)果中最后以.None結(jié)尾, 都需要在原來(lái)的查詢(xún)方法后面在跟上.all()才能獲得想要的結(jié)果
基于雙下線的跨表查詢(xún)
相當(dāng)于MySQL中的連表查詢(xún): 將兩張表或者對(duì)賬表連成一張表進(jìn)行查詢(xún)
正向查詢(xún)
正向查詢(xún), 按照關(guān)聯(lián)字段+雙下線>>> .values('關(guān)聯(lián)字段__被關(guān)聯(lián)表中的字段'), 返回的是一個(gè)QuerySet對(duì)象
一對(duì)一
查詢(xún)作者frank的手機(jī)號(hào)
res = Author.objects.filter(name='frank').values('detail__tel')
print(res)
# <QuerySet [{'detail__tel': '123456789'}]>
print(res.first())
# {'detail__tel': '123456789'}一對(duì)多
查詢(xún)?nèi)龂?guó)演義的出版社名字
res = Book.objects.filter(title='三國(guó)演義').values('publish__name')
print(res)
print(res.first())
# <QuerySet [{'publish__name': '北方出版社'}]>
# {'publish__name': '北方出版社'}多對(duì)多
查詢(xún)?nèi)龂?guó)演義的所有作者
res = Book.objects.filter(title='三國(guó)演義').values('authors__name')
print(res)
# <QuerySet [{'authors__name': 'frank'}, {'authors__name': 'lili'}]>反向查詢(xún)
按模型名(小寫(xiě))+雙下線>>> .values('表名小寫(xiě)__被關(guān)聯(lián)表中的字段'), 返回的是一個(gè)QuerySet對(duì)象.
一對(duì)一
查詢(xún)手機(jī)號(hào)為'123456789'的作者名
res = Author_Detail.objects.filter(tel='123456789').values('author__name')
print(res)
# <QuerySet [{'author__name': 'frank'}]>一對(duì)多
查詢(xún)北方出版社出版的所有書(shū)籍名字
res = Publish.objects.filter(name='北方出版社').values('book__title')
print(res)
# <QuerySet [{'book__title': '三國(guó)演義'}, {'book__title': '水滸傳'}]>多對(duì)多
查詢(xún)lili出版的所有書(shū)籍
res = Author.objects.filter(name='lili').values('book__title')
print(res)
# <QuerySet [{'book__title': '三國(guó)演義'}, {'book__title': '紅樓夢(mèng)'}, {'book__title': '西游記'}]>方法總結(jié):
正向查詢(xún),按關(guān)聯(lián)字段: .values('關(guān)聯(lián)字段__被關(guān)聯(lián)表中的字段'), 返回的是一個(gè)QuerySet對(duì)象
按模型名(小寫(xiě))+雙下線: .values('表名小寫(xiě)__被關(guān)聯(lián)表中的字段'), 返回的是一個(gè)QuerySet對(duì)象, 對(duì)象中保存的是字典類(lèi)型的數(shù)據(jù)
雙下高階正反向查詢(xún)
使用filter()的雙下線查詢(xún)
首先需要考慮的是正向查詢(xún)還是反向查詢(xún), 確定括號(hào)內(nèi)使用的方法, 但是括號(hào)外面不是使用values,而是使用filter!!!
注意: 使用filter方法字段是不能加引號(hào)的, values需要加引號(hào)
查詢(xún)書(shū)籍主鍵為反向, 使用.filter('表名小寫(xiě)__被關(guān)聯(lián)表中的字段')
res = Publish.objects.filter(book__pk= 4) print(res) # <QuerySet [<Publish: Publish object>]> res = Publish.objects.filter(book__title= '西游記') print(res) # 結(jié)果相同
連續(xù)跨多張表查詢(xún)
套路與上面的案例都是一樣的, 可以練習(xí)n個(gè)雙下劃線, 只需要在每次雙下線的時(shí)候, 確定是每個(gè)雙下線后面是正向查詢(xún)還是反向查詢(xún)即可
# 需求1:查詢(xún)北京出版社出版過(guò)的所有書(shū)籍的名字以及作者的姓名、手機(jī)號(hào)
# 方式一:基表為Publish
res=Publish.objects.filter(name='北方出版社').values_list('book__title','book__authors__name','book__authors__author_detail__tel')
# 方式二:基表為Book
res=Book.objects.filter(publish__name='北方出版社').values_list('title','authors__name','authors__author_detail__tel')
# 循環(huán)打印結(jié)果均為
for obj in res:
print(obj)
# 需求2:查詢(xún)手機(jī)號(hào)以186開(kāi)頭的作者出版過(guò)的所有書(shū)籍名稱(chēng)以及出版社名稱(chēng)
# 方式一:基表為AuthorDetail
res=AuthorDetail.objects.filter(tel__startswith='186').values_list('author__book__title','author__book__publish__name')
# 方式二:基表為Book
res=Book.objects.filter(authors__author_detail__tel__startswith='186').values_list('title','publish__name')
# 方式三:基表為Publish
res=Publish.objects.filter(book__authors__author_detail__tel__startswith='186').values_list('book__title','name')
# 循環(huán)打印結(jié)果均為
for obj in res:
print(obj)
到此這篇關(guān)于Django ORM 多表查詢(xún)的文章就介紹到這了,更多相關(guān)Django ORM 多表查詢(xún)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python協(xié)程異步爬取數(shù)據(jù)(asyncio+aiohttp)實(shí)例
這篇文章主要為大家介紹了Python協(xié)程異步爬取數(shù)據(jù)(asyncio+aiohttp)實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
Python實(shí)現(xiàn)敲擊木魚(yú)積累功德小項(xiàng)目
最近大家都很流行用手機(jī)敲擊電子木魚(yú)積累功德,這在很多短視頻中也常常見(jiàn)到。本文將用Python實(shí)現(xiàn)這一效果,感興趣的小伙伴可以了解一下2022-11-11
python實(shí)現(xiàn)撲克牌交互式界面發(fā)牌程序
這篇文章主要介紹了python實(shí)現(xiàn)撲克牌交互式界面發(fā)牌程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
python使用OpenCV模塊實(shí)現(xiàn)圖像的融合示例代碼
這篇文章主要介紹了python使用OpenCV模塊實(shí)現(xiàn)圖像的融合示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Python黑魔法Descriptor描述符的實(shí)例解析
與迭代器和裝飾器等一樣,描述符也是Python編程中的一項(xiàng)高級(jí)技巧,這里我們就來(lái)講解Python黑魔法Descriptor描述符的實(shí)例解析:2016-06-06
利用Python命令行傳遞實(shí)例化對(duì)象的方法
最近在工作中遇到了一個(gè)問(wèn)題,需要接收啟動(dòng)腳本傳遞過(guò)來(lái)的實(shí)例化后的對(duì)象,通過(guò)在網(wǎng)上查找資料發(fā)現(xiàn)了兩個(gè)方法,文中通過(guò)實(shí)例代碼就給大家詳細(xì)介紹了這兩種方法,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2016-11-11
Python實(shí)現(xiàn)telnet服務(wù)器的方法
這篇文章主要介紹了Python實(shí)現(xiàn)telnet服務(wù)器的方法,涉及Python通過(guò)Telnet連接服務(wù)器的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07

