聚合查詢
- 聚合查詢是指對(duì)一個(gè)數(shù)據(jù)表中的一個(gè)字段的數(shù)據(jù)進(jìn)行部分或全部進(jìn)行統(tǒng)計(jì)查詢,查bookstore_book數(shù)據(jù)表中的全部書(shū)的平均價(jià)格,查詢所有書(shū)的總個(gè)數(shù)等,都要使用聚合查詢
-
不帶分組聚合
不帶分組的聚合查詢是指導(dǎo)將全部數(shù)據(jù)進(jìn)行集中統(tǒng)計(jì)查詢
-
聚合函數(shù):
- 定義模塊:
django.db.models
- 用法:
from django.db.models import *
- 聚合函數(shù):
- Sum, Avg, Count, Max, Min
- 定義模塊:
-
語(yǔ)法:
- MyModel.objects.aggregate(結(jié)果變量名=聚合函數(shù)('列'))
-
返回結(jié)果:
- 由 結(jié)果變量名和值組成的字典
- 格式為:
{"結(jié)果變量名": 值}
-
示例:
# 得到所有書(shū)的平均價(jià)格 from bookstore import models from django.db.models import Count result = models.Book.objects.aggregate(myAvg=Avg('price')) print("平均價(jià)格是:", result['myAvg']) print("result=", result) # {"myAvg": 58.2} # 得到數(shù)據(jù)表里有多少本書(shū) from django.db.models import Count result = models.Book.objects.aggregate(mycnt=Count('title')) print("數(shù)據(jù)記錄總個(gè)數(shù)是:", result['mycnt']) print("result=", result) # {"mycnt": 10}
-
分組聚合
分組聚合是指通過(guò)計(jì)算查詢結(jié)果中每一個(gè)對(duì)象所關(guān)聯(lián)的對(duì)象集合砍聊,從而得出總計(jì)值(也可以是平均值或總和),即為查詢集的每一項(xiàng)生成聚合艾蓝。
-
語(yǔ)法:
- QuerySet.annotate(結(jié)果變量名=聚合函數(shù)('列'))
-
用法步驟:
-
通過(guò)先用查詢結(jié)果MyModel.objects.value. 查找查詢要分組聚合的列
MyModel.objects.value('列1', '列2')
-
如:
pub_set = models.Book.objects.values('pub') print(books) # <QuerySet [{'pub': '清華大學(xué)出版社'}, {'pub': '清華大學(xué)出版社'}, {'pub_hou {'pub': '機(jī)械工業(yè)出版社'}, {'pub': '清華大學(xué)出版社'}]>
-
通過(guò)返回結(jié)果的 QuerySet.annotate 方法分組聚合得到分組結(jié)果
QuerySet.annotate(名=聚合函數(shù)('列'))
返回 QuerySet 結(jié)果集,內(nèi)部存儲(chǔ)結(jié)果的字典
-
如:
pub_count_set = pub_set.annotate(myCount=Count('pub')) print(pub_count_set) # <QuerySet [{'pub': '清華大學(xué)出版社', 'myCount': 7}, {'pub': '機(jī)械工業(yè)出版社', 'myCount': 3}]>
- .values('查詢列名')
-
-
示例:
- 得到哪兒個(gè)出版社共出版多少本書(shū)
def test_annotate(request): - from django.db.models import Count from . import models # 得到所有出版社的查詢集合QuerySet pub_set = models.Book.objects.values('pub') # 根據(jù)出版社查詢分組摹量,出版社和Count的分組聚合查詢集合 pub_count_set = pub_set.annotate(myCount=Count('pub')) # 返回查詢集合 for item in pub_count_set: print("出版社:", item['pub'], "圖書(shū)有:", item['myCount']) return HttpResponse('請(qǐng)查看服務(wù)器端控制臺(tái)獲取結(jié)果')
F對(duì)象
- 一個(gè)F對(duì)象代表數(shù)據(jù)庫(kù)中某個(gè)字段的信息
- F對(duì)象通常是對(duì)數(shù)據(jù)庫(kù)中的字段值在不加載到內(nèi)存中的情況下直接在數(shù)據(jù)庫(kù)服務(wù)器端進(jìn)行操作
- F對(duì)象在 數(shù)據(jù)包 django.db.models 中.使用時(shí)需要通過(guò)如下語(yǔ)句進(jìn)行加載
from django.db.models import F
-
作用:
- 用于類(lèi)屬性(字段)之間的比較。
- 當(dāng)同時(shí)對(duì)數(shù)據(jù)庫(kù)中兩個(gè)字段的值進(jìn)行比較獲取 QuerySet 數(shù)據(jù)集時(shí)潮改,可以便用F對(duì)象
-
說(shuō)明:
- 一個(gè) F() 對(duì)象代表了一個(gè)model的字段的值
使用它就可以直接參考model的field和執(zhí)行數(shù)據(jù)庫(kù)操作而不用再把它們(model field)查詢出來(lái)放到python內(nèi)存中誉尖。
-
語(yǔ)法:
from django.db.models import F F('列名')
-
示例1
- 更新Book實(shí)例中所有的零售價(jià)漲10元
models.Book.objects.all().update(market_price=F('market_price')+10) # 以下做法好于如下代碼 books = models.Book.objects.all() for book in books: book.update(market_price=book.marget_price+10) book.save()
-
示例2
- 對(duì)數(shù)據(jù)庫(kù)中兩個(gè)字段的值進(jìn)行比較罪既,列出哪兒些書(shū)的零售價(jià)高于定價(jià)?
from django.db.models import F from bookstore import models books = models.Book.objects.filter(market_price__gt=F('price')) for book in books: print(book.title, '定價(jià):', book.price, '現(xiàn)價(jià):', book.market_price)
Q對(duì)象 - Q()
當(dāng)在獲取查詢結(jié)果集 使用復(fù)雜的邏輯或
|
、 邏輯非~
等操作時(shí)可以借助于 Q對(duì)象進(jìn)行操作-
如: 想找出定價(jià)低于20元 或 清華大學(xué)出版社的全部書(shū)铡恕,可以寫(xiě)成
models.Book.objects.filter(Q(price__lt=20)|Q(pub="清華大學(xué)出版社"))
-
Q對(duì)象在 數(shù)據(jù)包 django.db.models 中萝衩。需要先導(dǎo)入再使用
from django.db.models import Q
-
作用
- 在條件中用來(lái)實(shí)現(xiàn)除 and(&) 以外的 or(|) 或 not(~) 操作
-
運(yùn)算符:
- & 與操作
- | 或操作
- ? 非操作
-
語(yǔ)法
from django.db.models import Q Q(條件1)|Q(條件2) # 條件1成立或條件2成立 Q(條件1)&Q(條件2) # 條件1和條件2同時(shí)成立 Q(條件1)&~Q(條件2) # 條件1成立且條件2不成立 ...
-
示例
from django.db.models import Q # 查找清華大學(xué)出版社的書(shū)或價(jià)格低于50的書(shū) models.Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清華大學(xué)出版社')) # 查找不是機(jī)械工業(yè)出版社的書(shū)且價(jià)格低于50的書(shū) models.Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='機(jī)械工業(yè)出版社'))
原生的數(shù)據(jù)庫(kù)操作方法
使用MyModel.objects.raw()進(jìn)行 數(shù)據(jù)庫(kù)查詢操作查詢
- 在django中,可以使用模型管理器的raw方法來(lái)執(zhí)行select語(yǔ)句進(jìn)行數(shù)據(jù)查詢
-
語(yǔ)法:
MyModel.objects.raw(sql語(yǔ)句)
-
用法
MyModel.objects.raw('sql語(yǔ)句')
-
返回值:
- QuerySet 集合對(duì)象
-
示例
books = models.Book.objects.raw('select * from bookstore_book') for book in books: print(book)
使用django中的游標(biāo)cursor對(duì)數(shù)據(jù)庫(kù)進(jìn)行 增刪改操作
在Django中可以使用 如UPDATE,DELETE等SQL語(yǔ)句對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作没咙。
在DJaogo中使用上述非查詢語(yǔ)句必須使用游標(biāo)進(jìn)行操作
-
使用步驟:
- 導(dǎo)入cursor所在的包
- Django中的游標(biāo)cursor定義在 django.db.connection包中猩谊,使用前需要先導(dǎo)入
- 如:
from django.db import connection
- 用創(chuàng)建cursor類(lèi)的構(gòu)造函數(shù)創(chuàng)建cursor對(duì)象,再使用cursor對(duì)象,為保證在出現(xiàn)異常時(shí)能釋放cursor資源,通常使用with語(yǔ)句進(jìn)行創(chuàng)建操作
-
如:
from django.db import connection with connection.cursor() as cur: cur.execute('執(zhí)行SQL語(yǔ)句')
-
-
示例
# 用SQL語(yǔ)句將id 為 10的 書(shū)的出版社改為 "XXX出版社" from django.db import connection with connection.cursor() as cur: cur.execute('update bookstore_book set pub_house="XXX出版社" where id=10;') with connection.cursor() as cur: # 刪除 id為1的一條記錄 cur.execute('delete from bookstore_book where id=10;')
- 導(dǎo)入cursor所在的包
admin 后臺(tái)數(shù)據(jù)庫(kù)管理
- django 提供了比較完善的后臺(tái)管理數(shù)據(jù)庫(kù)的接口祭刚,可供開(kāi)發(fā)過(guò)程中調(diào)用和測(cè)試使用
- django 會(huì)搜集所有已注冊(cè)的模型類(lèi)牌捷,為這些模型類(lèi)提拱數(shù)據(jù)管理界面,供開(kāi)發(fā)者使用
- 使用步驟:
-
創(chuàng)建后臺(tái)管理帳號(hào):
-
后臺(tái)管理--創(chuàng)建管理員帳號(hào)
$ python3 manage.py createsuperuser
- 根據(jù)提示完成注冊(cè),參考如下:
$ python3 manage.py createsuperuser Username (leave blank to use 'tarena'): tarena # 此處輸入用戶名 Email address: weimz@tedu.cn # 此處輸入郵箱 Password: # 此處輸入密碼(密碼要復(fù)雜些涡驮,否則會(huì)提示密碼太簡(jiǎn)單) Password (again): # 再次輸入重復(fù)密碼 Superuser created successfully. $
-
-
用注冊(cè)的帳號(hào)登陸后臺(tái)管理界面
- 后臺(tái)管理的登錄地址:
-
自定義后臺(tái)管理數(shù)據(jù)表
- 若要自己定義的模型類(lèi)也能在
/admin
后臺(tái)管理界中顯示和管理暗甥,需要將自己的類(lèi)注冊(cè)到后臺(tái)管理界面 - 添加自己定義模型類(lèi)的后臺(tái)管理數(shù)據(jù)表的,需要用
admin.site.register(自定義模型類(lèi))
方法進(jìn)行注冊(cè)-
配置步驟如下:
-
在應(yīng)用app中的admin.py中導(dǎo)入注冊(cè)要管理的模型models類(lèi), 如:
from . import models
-
調(diào)用 admin.site.register 方法進(jìn)行注冊(cè),如:
from django.contrib import admin admin.site.register(自定義模型類(lèi))
-
如: 在 bookstore/admin.py 添加如下代碼對(duì)Book類(lèi)進(jìn)行管理
-
示例:
# file: bookstore/admin.py from django.contrib import admin # Register your models here. from . import models ... admin.site.register(models.Book) # 將Book類(lèi)注冊(cè)為可管理頁(yè)面
-
修改后臺(tái)Models的展現(xiàn)形式
在admin后臺(tái)管理數(shù)據(jù)庫(kù)中對(duì)自定義的數(shù)據(jù)記錄都展示為
XXXX object
類(lèi)型的記錄,不便于閱讀和判斷-
在用戶自定義的模型類(lèi)中可以重寫(xiě)
def __str__(self):
方法解決顯示問(wèn)題,如:- 在 自定義模型類(lèi)中重寫(xiě) str(self) 方法返回顯示文字內(nèi)容:
class Book(models.Model): ... def __str__(self): return "書(shū)名" + self.title
模型管理器類(lèi)
-
作用:
- 為后臺(tái)管理界面添加便于操作的新功能捉捅。
-
說(shuō)明:
- 后臺(tái)管理器類(lèi)須繼承自
django.contrib.admin
里的ModelAdmin
類(lèi)
- 后臺(tái)管理器類(lèi)須繼承自
-
模型管理器的使用方法:
-
在
<應(yīng)用app>/admin.py
里定義模型管理器類(lèi)class XXXX_Manager(admin.ModelAdmin): ......
-
注冊(cè)管理器與模型類(lèi)關(guān)聯(lián)
from django.contrib import admin from . import models admin.site.register(models.YYYY, XXXX_Manager) # 注冊(cè)models.YYYY 模型類(lèi)與 管理器類(lèi) XXXX_Manager 關(guān)聯(lián)
-
示例:
# file : bookstore/admin.py from django.contrib import admin from . import models class BookAdmin(admin.ModelAdmin): list_display = ['id', 'title', 'price', 'market_price'] admin.site.register(models.Book, BookAdmin)
- 進(jìn)入http://127.0.0.1:8000/admin/bookstore/book/ 查看顯示方式和以前有所不同
-
-
模型管理器類(lèi)ModelAdmin中實(shí)現(xiàn)的高級(jí)管理功能
- list_display 去控制哪些字段會(huì)顯示在Admin 的修改列表頁(yè)面中撤防。
- list_display_links 可以控制list_display中的字段是否應(yīng)該鏈接到對(duì)象的“更改”頁(yè)面。
- list_filter 設(shè)置激活A(yù)dmin 修改列表頁(yè)面右側(cè)欄中的過(guò)濾器
- search_fields 設(shè)置啟用Admin 更改列表頁(yè)面上的搜索框棒口。
- list_editable 設(shè)置為模型上的字段名稱(chēng)列表寄月,這將允許在更改列表頁(yè)面上進(jìn)行編輯。
- 其它參見(jiàn)https://docs.djangoproject.com/en/1.11/ref/contrib/admin/
數(shù)據(jù)庫(kù)表管理
-
修改模型類(lèi)字段的顯示名字
模型類(lèi)各字段的第一個(gè)參數(shù)為 verbose_name,此字段顯示的名字會(huì)在后臺(tái)數(shù)據(jù)庫(kù)管理頁(yè)面顯示
-
通過(guò) verbose_name 字段選項(xiàng),修改顯示名稱(chēng)示例如下:
title = models.CharField( max_length = 30, verbose_name='顯示名稱(chēng)' )
-
通過(guò)Meta內(nèi)嵌類(lèi) 定義模型類(lèi)的屬性及展現(xiàn)形式
模型類(lèi)可以通過(guò)定義內(nèi)部類(lèi)class Meta 來(lái)重新定義當(dāng)前模型類(lèi)和數(shù)據(jù)表的一些屬性信息
-
用法格式如下:
class Book(models.Model): title = CharField(....) class Meta: 1. db_table = '數(shù)據(jù)表名' - 該模型所用的數(shù)據(jù)表的名稱(chēng)无牵。(設(shè)置完成后需要立馬更新同步數(shù)據(jù)庫(kù)) 2. verbose_name = '單數(shù)名' - 給模型對(duì)象的一個(gè)易于理解的名稱(chēng)(單數(shù)),用于顯示在/admin管理界面中 3. verbose_name_plural = '復(fù)數(shù)名' - 該對(duì)象復(fù)數(shù)形式的名稱(chēng)(復(fù)數(shù)),用于顯示在/admin管理界面中
-
示例:
class Meta: db_table = 'book_table' # 將原數(shù)據(jù)表名"bookstore_book" 換為 "book_table",請(qǐng)查看數(shù)據(jù)表 verbose_name = 'booooook' verbose_name_plural = 'booksssssss' # 去127.0.0.1:8000/admin下看看哪兒變化了?
- 練習(xí):
- 將Book模型類(lèi) 和 Author 模型類(lèi)都加入后臺(tái)管理
- 制作一個(gè)AuthorManager管理器類(lèi)漾肮,讓后臺(tái)管理Authors列表中顯示作者的ID、姓名茎毁、年齡信息
- 用后臺(tái)管理程序 添加三條 Author 記錄
- 修改其中一條記錄的年齡
- 刪除最后一條添加的記錄
- 將bookstore_author 數(shù)名表名稱(chēng)改為myauthor (需要重新遷移數(shù)據(jù)庫(kù))
數(shù)據(jù)表關(guān)聯(lián)關(guān)系映射 Relationship Map
- 在關(guān)系型數(shù)據(jù)庫(kù)中克懊,通常不會(huì)把所有數(shù)據(jù)都放在同一張表中,這樣做會(huì)額外占用內(nèi)存空間,
- 在關(guān)系列數(shù)據(jù)庫(kù)中通常用表關(guān)聯(lián)來(lái)解決數(shù)據(jù)庫(kù)谭溉。
- 常用的表關(guān)聯(lián)方式有三種:
- 一對(duì)一映射
- 如: 一個(gè)身份證對(duì)應(yīng)一個(gè)人
- 一對(duì)多映射
- 如: 一個(gè)班級(jí)可以有多個(gè)學(xué)生
- 多對(duì)多映射
- 如: 一個(gè)學(xué)生可以報(bào)多個(gè)課程墙懂,一個(gè)課程可以有多個(gè)學(xué)生學(xué)習(xí)
- 一對(duì)一映射
一對(duì)一映射
- 一對(duì)一是表示現(xiàn)實(shí)事物間存在的一對(duì)一的對(duì)應(yīng)關(guān)系。
- 如:一個(gè)家庭只有一個(gè)戶主扮念,一個(gè)男人有一個(gè)妻子垒在,一個(gè)人有一個(gè)唯一的指紋信息等
-
語(yǔ)法
在關(guān)聯(lián)的兩個(gè)類(lèi)中的任何一個(gè)類(lèi)中: class A(model.Model): ... class B(model.Model): 屬性 = models.OneToOneField(A)
-
用法示例
-
創(chuàng)建作家和作家妻子類(lèi)
# file : xxxxxxxx/models.py from django.db import models class Author(models.Model): '''作家模型類(lèi)''' name = models.CharField('作家', max_length=50) class Wife(models.Model): '''作家妻子模型類(lèi)''' name = models.CharField("妻子", max_length=50) author = models.OneToOneField(Author) # 增加一對(duì)一屬性
-
查詢
- 在 Wife 對(duì)象中,通過(guò) author 屬性找到對(duì)應(yīng)的author對(duì)象
- 在 Author 對(duì)象中,通過(guò) wife 屬性找到對(duì)應(yīng)的wife對(duì)象
-
創(chuàng)始一對(duì)一的數(shù)據(jù)記錄
from . import models author1 = models.Author.objects.create(name='王老師') wife1 = models.Wife.objects.create(name='王夫人', author=author1) # 關(guān)聯(lián)王老師 author2 = models.Author.objects.create(name='小澤老師') # 一對(duì)一可以沒(méi)有數(shù)據(jù)對(duì)應(yīng)的數(shù)據(jù)
-
一對(duì)一數(shù)據(jù)的相互獲取
-
正向查詢
- 直接通過(guò)關(guān)聯(lián)屬性查詢即可
# 通過(guò) wife 找 author from . import models wife = models.Wife.objects.get(name='王夫人') print(wife.name, '的老公是', wife.author.name)
-
反向查詢
- 通過(guò)反向引用屬性查詢
- 反向引用屬性為
實(shí)例對(duì)象.引用類(lèi)名(小寫(xiě))
,如作家的反向引用為作家對(duì)象.wife
- 當(dāng)反向引用不存在時(shí)扔亥,則會(huì)觸發(fā)異常
# 通過(guò) author.wife 引用屬性 找 wife,如果沒(méi)有對(duì)應(yīng)的wife剛觸發(fā)異常 author1 = models.Author.objects.get(name='王老師') print(author1.name, '的妻子是', author1.wife.name) author2 = models.Author.objects.get(name='小澤老師') try: print(author2.name, '的妻子是', author2.wife.name) except: print(author2.name, '還沒(méi)有妻子')
-
-
-
作用:
- 主要是解決常用數(shù)據(jù)不常用數(shù)據(jù)的存儲(chǔ)問(wèn)題,把經(jīng)常加載的一個(gè)數(shù)據(jù)放在主表中,不常用數(shù)據(jù)放在另一個(gè)副表中谈为,這樣在訪問(wèn)主表數(shù)據(jù)時(shí)不需要加載副表中的數(shù)據(jù)以提高訪問(wèn)速度提高效率和節(jié)省內(nèi)存空間,如經(jīng)常把書(shū)的內(nèi)容和書(shū)名建成兩張表旅挤,因?yàn)樵诰W(wǎng)站上經(jīng)常訪問(wèn)書(shū)名等信息,但不需要得到書(shū)的內(nèi)容伞鲫。
-
練習(xí):
- 創(chuàng)建一個(gè)Wife模型類(lèi),屬性如下
- name
- age
- 在Wife類(lèi)中增加一對(duì)一關(guān)聯(lián)關(guān)系,引用 Author
- 同步回?cái)?shù)據(jù)庫(kù)并觀察結(jié)果
- 創(chuàng)建一個(gè)Wife模型類(lèi),屬性如下
一對(duì)多映射
- 一對(duì)多是表示現(xiàn)實(shí)事物間存在的一對(duì)多的對(duì)應(yīng)關(guān)系粘茄。
- 如:一個(gè)學(xué)校有多個(gè)班級(jí),一個(gè)班級(jí)有多個(gè)學(xué)生, 一本圖書(shū)只能屬于一個(gè)出版社,一個(gè)出版社允許出版多本圖書(shū)
-
用法語(yǔ)法
- 當(dāng)一個(gè)A類(lèi)對(duì)象可以關(guān)聯(lián)多個(gè)B類(lèi)對(duì)象時(shí)
class A(model.Model): ... class B(model.Model): 屬性 = models.ForeignKey(多對(duì)一中"一"的模型類(lèi), ...)
-
外鍵類(lèi)ForeignKey
-
構(gòu)造函數(shù):
ForeignKey(to, on_delete, **options)
-
常用參數(shù):
- on_delete
- models.CASCADE 級(jí)聯(lián)刪除。 Django模擬SQL約束ON DELETE CASCADE的行為秕脓,并刪除包含F(xiàn)oreignKey的對(duì)象柒瓣。
- models.PROTECT 拋出ProtectedError 以阻止被引用對(duì)象的刪除;
- SET_NULL 設(shè)置ForeignKey null;只有null是True才有可能吠架。
- SET_DEFAULT 將ForeignKey設(shè)置為其默認(rèn)值芙贫;必須設(shè)置ForeignKey的默認(rèn)值。
- ... 其它參請(qǐng)參考文檔 https://docs.djangoproject.com/en/1.11/ref/models/fields/#foreignkey ForeignKey部分
-
**options
可以是常用的字段選項(xiàng)如:- null
- unique等
- ...
- on_delete
-
-
示例
- 有二個(gè)出版社對(duì)應(yīng)五本書(shū)的情況.
-
清華大學(xué)出版社
有書(shū)- C++
- Java
- Python
-
北京大學(xué)出版社
有書(shū)- 西游記
- 水滸
-
-
定義一對(duì)多類(lèi)
# file: myorm/models.py from django.db import models class Publisher(models.Model): '''出版社''' name = models.CharField('名稱(chēng)', max_length=50, unique=True) class Book(models.Model): title = models.CharField('書(shū)名', max_length=50) publisher = models.ForeignKey(Publisher, null=True)
-
創(chuàng)建一對(duì)多的對(duì)象
# file: xxxxx/views.py from . import models pub1 = models.Publisher.objects.create(name='清華大學(xué)出版社') models.Book.objects.create(title='C++', publisher=pub1) models.Book.objects.create(title='Java', publisher=pub1) models.Book.objects.create(title='Python', publisher=pub1) pub2 = models.Publisher.objects.create(name='北京大學(xué)出版社') models.Book.objects.create(title='西游記', publisher=pub2) models.Book.objects.create(title='水滸', publisher=pub2)
-
查詢:
- 通過(guò)多查一
# 通過(guò)一本書(shū)找到對(duì)應(yīng)的出版社 abook = models.Book.objects.get(id=1) print(abook.title, '的出版社是:', abook.publisher.name)
- 通過(guò)一查多
# 通過(guò)出版社查詢對(duì)應(yīng)的書(shū) pub1 = models.Publisher.objects.get(name='清華大學(xué)出版社') books = pub1.book_set.all() # 通過(guò)book_set 獲取pub1對(duì)應(yīng)的多個(gè)Book數(shù)據(jù)對(duì)象 # books = models.Book.objects.filter(publisher=pub1) # 也可以采用此方式獲取 print("清華大學(xué)出版社的書(shū)有:") for book in books: print(book.title)
- 有二個(gè)出版社對(duì)應(yīng)五本書(shū)的情況.
- 練習(xí):
- 完成Book 和 Publisher 之間的一對(duì)多
- 查看數(shù)據(jù)庫(kù)效果
- 登錄到后臺(tái),查看Book實(shí)體
- 數(shù)據(jù)查詢
-
通過(guò) Book 查詢 Publisher
通過(guò) publisher 屬性查詢即可 練習(xí): 查詢 西游記 對(duì)應(yīng)的出版社信息,打印在終端上
-
通過(guò) Publisher 查詢 對(duì)應(yīng)的所有的 Books
Django會(huì)在Publisher中增加一個(gè)屬性來(lái)表示對(duì)對(duì)應(yīng)的Book們的查詢引用 屬性:book_set(MyModel.objects)
-
多對(duì)多映射
- 多對(duì)多表達(dá)對(duì)象之間多對(duì)多復(fù)雜關(guān)系傍药,如: 每個(gè)人都有不同的學(xué)校(小學(xué)磺平,初中,高中,...),每個(gè)學(xué)校都有不同的學(xué)生...
-
語(yǔ)法
在關(guān)聯(lián)的兩個(gè)類(lèi)中的任意一個(gè)類(lèi)中,增加: 屬性 = models.ManyToManyField(MyModel)
-
示例
一個(gè)作者可以出版多本圖書(shū) 一本圖書(shū)可以被多名作者同時(shí)編寫(xiě) class Author(models.Model): xxxx xxxx class Book(models.Model): xxxx xxxx authors = models.ManyToManyField(Author)
-
數(shù)據(jù)查詢
-
通過(guò) Book 查詢對(duì)應(yīng)的所有的 Authors
可以通過(guò)authors表示對(duì)應(yīng)所有Author的查詢對(duì)象 book.authors.all() -> 獲取 book 對(duì)應(yīng)的所有的author的信息 book.authors.filter(age__gt=80) -> 獲取book對(duì)應(yīng)的作者中年齡大于80歲的作者的信息
-
通過(guò) Author 查詢對(duì)應(yīng)的所有的Books
Django會(huì)生成一個(gè)屬性 book_set 用于表示對(duì)對(duì)應(yīng)的book的查詢對(duì)象相關(guān)操作? author.book_set.all() author.book_set.filter() author.book_set.create(...) # 創(chuàng)建新書(shū)并聯(lián)作用author author.book_set.add(book) # 添加已有的書(shū)為當(dāng)前作者author author.book_set.clear() # 刪除author所有并聯(lián)的書(shū) author.book_set.remove() # 刪除所author所有并聯(lián)的書(shū)
-
-
示例:
- 多對(duì)多模型
class Author(models.Model): '''作家模型類(lèi)''' name = models.CharField('作家', max_length=50) def __str__(self): return self.name class Book(models.Model): title = models.CharField('書(shū)名', max_length=50) author = models.ManyToManyField(Author, null=True) def __str__(self): return self.title
- 多對(duì)多視圖操作
from django.http import HttpResponse from . import models def many2many_init(request): # 創(chuàng)建兩人個(gè)作者 author1 = models.Author.objects.create(name='呂澤') author2 = models.Author.objects.create(name='魏老師') # 呂擇和魏老師同時(shí)寫(xiě)了一本Python book11 = author1.book_set.create(title="Python") author2.book_set.add(book11) # # 魏老師還寫(xiě)了兩本書(shū) book21 = author2.book_set.create(title="C") # 創(chuàng)建一本新書(shū)"C" book22 = author2.book_set.create(title="C++") # 創(chuàng)建一本新書(shū)"C++" return HttpResponse("初始化成功") def show_many2many(request): authors = models.Author.objects.all() for auth in authors: print("作者:", auth.name, '發(fā)出版了', auth.book_set.count(), '本書(shū): ') for book in books: print(' ', book.title) print("----顯示書(shū)和作者的關(guān)系----") books = models.Book.objects.all() for book in books: auths = book.author.all() print(book.title, '的作者是:', '拐辽、'.join([str(x.name) for x in auths])) return HttpResponse("顯示成功拣挪,請(qǐng)查看服務(wù)器端控制臺(tái)終端")
- 多對(duì)多最終的SQL結(jié)果
mysql> select * from myorm2_author; +----+-----------+ | id | name | +----+-----------+ | 11 | 呂澤 | | 12 | 魏老師 | +----+-----------+ 2 rows in set (0.00 sec) mysql> select * from myorm2_book; +----+--------+ | id | title | +----+--------+ | 13 | Python | | 14 | C | | 15 | C++ | +----+--------+ 3 rows in set (0.00 sec) mysql> select * from myorm2_book_author; +----+---------+-----------+ | id | book_id | author_id | +----+---------+-----------+ | 17 | 13 | 11 | | 20 | 13 | 12 | | 18 | 14 | 12 | | 19 | 15 | 12 | +----+---------+-----------+ 4 rows in set (0.00 sec)
- 示例示意圖 [圖片上傳失敗...(image-ed69a-1563362158182)]