您好,登錄后才能下訂單哦!
一、創(chuàng)建模型
1,一對(duì)多關(guān)系
一本書只有一個(gè)出版社,一個(gè)出版社可以出版多本書,從而書與出版社之間就構(gòu)成一對(duì)多關(guān)系,書是‘多'的一方,出版社是‘一'的一方,我們?cè)诮⒛P偷臅r(shí)候,把外鍵寫在‘多'的一方,即我們要把外鍵寫在book類。
class Book(models.Model): name=models.CharField(max_length=15) price=models.IntegerField() publish=models.ForeignKey('Publish',on_delete=models.CASCADE) #這就是外鍵,其實(shí)是有三個(gè)參數(shù)的,第二參數(shù)是指向的字段,此處可以省略,他會(huì)自動(dòng)指向id字段 class Publish(models.Model): name=models.CharField(max_length=15) addr=models.CharField(max_length=15) phone=models.IntegerField()
在創(chuàng)建模型時(shí)不用創(chuàng)建id字段,在makemigrations命令輸入之后,它會(huì)在migrations文件夾下生產(chǎn)一個(gè)py文件記錄models.py里面所有的改動(dòng),在記錄的時(shí)候就會(huì)自動(dòng)給你加上自增長(zhǎng)的主鍵字段id。
2,多對(duì)多關(guān)系
一本書可以有多個(gè)作者,一個(gè)作者可以寫多本書,從而書和作者就構(gòu)成了多對(duì)多的關(guān)系,我們?cè)趧?chuàng)建模型的時(shí)候,把多對(duì)多關(guān)系寫在其中的任何一張表都可以。
class Book(models.Model): name=models.CharField(max_length=15) price=models.IntegerField() publish=models.CharField(max_length=15) author=models.ManyToManyField('Author',db_table='book_author') 這是創(chuàng)建關(guān)系表的代碼,由于是寫在book模型中的,所以第一個(gè)參數(shù)為另一張表Author,第二個(gè)參數(shù)為把關(guān)系表的名字改為‘book_author',如果不寫, 名字會(huì)是應(yīng)用名_本模型名的小寫_另一張模型名的小寫。如‘a(chǎn)pp_book_author' class Meta: 這是把表名改為‘book',如果不寫,表名為APP名_模型名,如'app_book' db_table='book' class Author(models.Model): name=models.CharField(max_length=15) age=models.IntegerField() class Meta: db_table='author' 在創(chuàng)建第三張模型的時(shí)候也不用指定book的id和author的id,它會(huì)自動(dòng)把兩個(gè)模型的id字段寫進(jìn)去的
3,一對(duì)一關(guān)系
一個(gè)作者只能對(duì)應(yīng)一個(gè)作者詳細(xì)信息表,他們之間就是一對(duì)一關(guān)系,這和多對(duì)多一樣的,關(guān)系寫在哪張表都是可以的
class Author(models.Model): name=models.CharField(max_length=15) age=models.IntegerField() author_info=models.OneToOneField('Author_Info',on_delete=models.CASCADE) 這是一對(duì)一關(guān)系創(chuàng)建,第二參數(shù)是,自動(dòng)跟隨刪除,當(dāng)作者不在了,隨即作者的信息也會(huì)刪除 class Meta: db_table='author' class Author_Info(models.Model): gf_name=models.CharField(max_length=10) telephone=models.IntegerField() ShenFenZheng=models.IntegerField()
4,在此處我們可以使用Django的database:db.sqlite3
步驟如下:
5,數(shù)據(jù)庫(kù)遷移
由于Django默認(rèn)就是db.sqlite,所以我們不用去settings配置,也不需要在項(xiàng)目的__init__.py里寫代碼,現(xiàn)在只需要輸入兩條數(shù)據(jù)庫(kù)遷移指令就行了
點(diǎn)擊這里之后進(jìn)入:
在這里數(shù)輸入指令,就不需要寫python manage.py了,因?yàn)橐呀?jīng)進(jìn)入到manage.py
現(xiàn)在輸入makemigrations指令 #記錄models.py文件發(fā)生的改變,然后在migrations文件夾下生產(chǎn)一個(gè)py文件,里面記錄發(fā)生的變化
再輸入migrate指令 #執(zhí)行migrations文件下新變動(dòng)的遷移文件,去更新數(shù)據(jù)庫(kù)
到此,表就創(chuàng)建成功了。
二、添加表記錄
1,一對(duì)多關(guān)系
之前我們創(chuàng)建了Book表和Publish表,兩者就是一對(duì)多的關(guān)系,Book表是‘多'的一方,所以外鍵字段在Book表,Book表添加和之前的不一樣,而‘一'的Publish表就是一張單表,和之前的一樣,所以我們只要學(xué)習(xí)‘多'的一張Book表的添加就行了。添加表記錄有兩種方式。
1.1 按models.py里面Book類的屬性來添加
pub=Publish.objects.all().filter(id=1).first() #首先找到id為1的Publish對(duì)象 book=Book.objects.create(name=name,price=price,publish=pub,pub_date=pub_date) #然后把這一對(duì)象賦值給Book類的publish屬性
1.2 按數(shù)據(jù)庫(kù)里面Book表的字段來添加
book=Book.objects.create(name=name,price=price,publish_id=1,pub_date=pub_date) #直接把Publish的id賦值給book表的publish_id就行了
2,多對(duì)多關(guān)系
之前我們創(chuàng)建了Book表和Author表,兩者就是多對(duì)多關(guān)系,我是把多對(duì)多關(guān)系寫在book表中的,所以從book去添加關(guān)聯(lián)關(guān)系是正向的。
# 當(dāng)前生成的書籍對(duì)象 book_obj=Book.objects.create(title="追風(fēng)箏的人",price=200,publishDate="2012-11-12",publish_id=1) # 為書籍綁定的作者對(duì)象 a1=Author.objects.filter(id=2).first() # 在Author表中主鍵為2的紀(jì)錄 a2=Author.objects.filter(id=1).first() # 在Author表中主鍵為1的紀(jì)錄 # 綁定多對(duì)多關(guān)系,即向關(guān)系表book_authors中添加紀(jì)錄,正向用屬性,反向用表名_set 第一種,以Book為基表,因?yàn)槎鄬?duì)多關(guān)系是寫在Book中的,所以現(xiàn)在屬于正向關(guān)聯(lián),用屬性 book_obj.author.add(author1,author2) #這是給book_obj對(duì)象綁定上author1和author2兩個(gè)對(duì)象。這里的author不是Author小寫,而是Book類的一個(gè)屬性 第二種,以Author為基表,因?yàn)槎鄬?duì)多關(guān)系不是寫在Author表,所以屬于反向關(guān)聯(lián),用表名小寫_set author_obj.book_set.add(book1,book2) #這是給author_obj對(duì)象綁定上book1和book2兩個(gè)對(duì)象,但是這里book可不是Author類的屬性,而且也沒有這個(gè)屬性,它是Book表小寫后得到的 關(guān)系表的方法: 1,add()方法 參數(shù)可以是可以是n個(gè)模型類對(duì)象,如上面的寫法 也可以是一個(gè)queryset集合,如author_list=Author.objects.filter(id__gt=2),這是找出id大于2的作者集合 book_obj.author.add(*author_list) 還可以是一個(gè)主鍵列表,如下面的寫法 book_obj.author.add(*[1,3,4]) 2,remove()方法,移出關(guān)系方法 現(xiàn)在book1關(guān)聯(lián)著author1和author2兩個(gè)作者 book1.author.remove(author1) #此時(shí)book1就關(guān)聯(lián)author2一個(gè)作者 反向也行author2.book_set.remove(book2) #把a(bǔ)uthor2的關(guān)聯(lián)書籍book2給移出 3,clear()方法,清空關(guān)系方法 book1.author.clear() #把book1的所有關(guān)聯(lián)關(guān)系給刪除,現(xiàn)在book1就沒有關(guān)聯(lián)作者了 author1.book_set.clear() 一樣的,把a(bǔ)uthor1的所有關(guān)聯(lián)書籍的關(guān)聯(lián)關(guān)系刪除 4,set()方法,先把關(guān)聯(lián)關(guān)系清空,再添加關(guān)聯(lián)關(guān)系 假如book1關(guān)聯(lián)著author1 book1.author.set(author2) 先把與author1的關(guān)聯(lián)關(guān)系刪除,然后再建立與author2的關(guān)聯(lián)關(guān)系 假如author3關(guān)聯(lián)著book1 author3.book_set.set(book2) 先把關(guān)聯(lián)關(guān)系清空,再建立與book2的關(guān)聯(lián)關(guān)系 5,=方法,賦值一個(gè)可迭代對(duì)象,關(guān)聯(lián)關(guān)系會(huì)被整體替換 假如book1關(guān)聯(lián)author1 new_list=[author2,author3] book1.author=new_list 這也會(huì)先把關(guān)聯(lián)關(guān)系清空,然后把列表里的對(duì)象與book1建立關(guān)聯(lián)關(guān)系
3,一對(duì)一關(guān)系
之前創(chuàng)建的Author表和Author_Info表之間就是一對(duì)一關(guān)系,我把關(guān)聯(lián)字段寫在了Author表中。
給Author類的屬性賦值 info=Author_Info.objects.create(gf_name=gf_name,telephone=telephone,ShenFenZheng=ShenFenZheng) #這是創(chuàng)建了一條Author_Info記錄,info就是一個(gè)Author_info對(duì)象 Author.objects.create(name=name,age=age,author_info=info) 把創(chuàng)建的info對(duì)象賦值給author_info屬性 和一對(duì)多一樣,也可以使用Author表的字段賦值 Author.objects.create(name=name,age=age,author_info_id=2)
三、基于對(duì)象的跨表查詢(就是子查詢)
1,一對(duì)多查詢(Book與Publish)
1.1 正向查詢(按屬性:publish)
# 查詢主鍵為1的書籍的出版社所在的城市 book_obj=Book.objects.filter(pk=1).first() # book_obj.publish 是主鍵為1的書籍對(duì)象關(guān)聯(lián)的出版社對(duì)象 print(book_obj.publish.city)
1.2 反向查詢(按表名小寫_set:book_set)
publish=Publish.objects.get(name="蘋果出版社") #publish.book_set.all() : 與蘋果出版社關(guān)聯(lián)的所有書籍對(duì)象集合 book_list=publish.book_set.all() for book_obj in book_list: print(book_obj.title)
2,一對(duì)一查詢(Author與Author_Info)
2.1 正向查詢(按屬性:author_info)
egon=Author.objects.filter(name="egon").first() print(egon.authorDetail.telephone)
2.2 反向查詢(按表名小寫:author)
# 查詢所有住址在北京的作者的姓名 authorDetail_list=AuthorDetail.objects.filter(addr="beijing") for obj in authorDetail_list: print(obj.author.name)
3,多對(duì)多查詢(Author與Book)
3.1 正向查詢(按屬性:author)
# 金瓶眉所有作者的名字以及手機(jī)號(hào) book_obj=Book.objects.filter(title="金瓶眉").first() authors=book_obj.authors.all() for author_obj in authors: print(author_obj.name,author_obj.authorDetail.telephone)
3.2 反向查詢(按表名小寫_set:book_set)
# 查詢egon出過的所有書籍的名字 author_obj=Author.objects.get(name="egon") book_list=author_obj.book_set.all() #與egon作者相關(guān)的所有書籍 for book_obj in book_list: print(book_obj.title)
4,related_name設(shè)置
可以通過Foreignkey和MangToMangField的定義中設(shè)置related_name的值來復(fù)寫foo_set的名稱。 publish=ForeignKey('Publish',related_name='booklist') #這樣之后,反向就不用表名_set,就用booklist # 查詢 人民出版社出版過的所有書籍 publish=Publish.objects.get(name="人民出版社") book_list=publish.bookList.all() # 與人民出版社關(guān)聯(lián)的所有書籍對(duì)象集合
四、基于雙下劃線的跨表查詢
Django還提供了一種直觀而高效的方式在查詢中表示關(guān)聯(lián)關(guān)系,它能自動(dòng)確認(rèn)sql join聯(lián)系。要做跨關(guān)系查詢,就使用兩個(gè)下劃線來鏈接模型間關(guān)聯(lián)字段的名稱,直到最終連接到想要的model為止。
正向查詢按屬性,反向查詢按表名小寫
1,一對(duì)多查詢
# 練習(xí): 查詢蘋果出版社出版過的所有書籍的名字與價(jià)格(一對(duì)多) # 正向查詢 按字段:publish queryResult=Book.objects .filter(publish__name="蘋果出版社") .values_list("title","price") # 反向查詢 按表名:book queryResult=Publish.objects .filter(name="蘋果出版社") .values_list("book__title","book__price")
2,多對(duì)多查詢
# 練習(xí): 查詢alex出過的所有書籍的名字(多對(duì)多) # 正向查詢 按字段:authors: queryResult=Book.objects .filter(authors__name="yuan") .values_list("title") # 反向查詢 按表名:book queryResult=Author.objects .filter(name="yuan") .values_list("book__title","book__price")
3,一對(duì)一關(guān)系
# 查詢alex的手機(jī)號(hào) # 正向查詢 ret=Author.objects.filter(name="alex").values("authordetail__telephone") # 反向查詢 ret=AuthorDetail.objects.filter(author__name="alex").values("telephone")
4,進(jìn)階練習(xí)
# 練習(xí): 查詢?nèi)嗣癯霭嫔绯霭孢^的所有書籍的名字以及作者的姓名 # 正向查詢 queryResult=Book.objects .filter(publish__name="人民出版社") .values_list("title","authors__name") # 反向查詢 queryResult=Publish.objects .filter(name="人民出版社") .values_list("book__title","book__authors__age","book__authors__name") # 練習(xí): 手機(jī)號(hào)以151開頭的作者出版過的所有書籍名稱以及出版社名稱 # 方式1: queryResult=Book.objects .filter(authors__authorDetail__telephone__regex="151") .values_list("title","publish__name") # 方式2: ret=Author.objects .filter(authordetail__telephone__startswith="151") .values("book__title","book__publish__name")
五、聚合查詢與分組查詢
1,聚合
aggregate(*args,**kwargs)是Queryset的一個(gè)終止子句,意思是說,它返回一個(gè)包含一些鍵值對(duì)的字典。鍵的名稱是按照字段和聚合函數(shù)的名稱自動(dòng)生成出來的 計(jì)算所有圖書的平均價(jià)格 from django.db.models import Avg Book.objects.all().aggregate(Avg('price')) 結(jié)果:{'price__avg': 34.35} 如果你想要為聚合值指定一個(gè)名稱,可以向聚合函數(shù)前面用一個(gè)變量名來接收,此時(shí),鍵的名稱就變?yōu)榻邮盏淖兞棵?Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} 在終止子句里面可以放多個(gè)聚合函數(shù),得到結(jié)果就是有多個(gè)鍵值對(duì) from django.db.models import Avg, Max, Min Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} aggregate()只能對(duì)一個(gè)分組有用,對(duì)于按某字段分完組后的n個(gè)組,此時(shí)aggregate()就不能循環(huán)對(duì)每個(gè)分組作用,它只會(huì)得到第一組的結(jié)果
2,分組
2.1 單表分組查詢
查詢每一個(gè)部門名稱以及對(duì)應(yīng)的員工數(shù) emp: id name age salary dep alex 12 2000 銷售部 egon 22 3000 人事部 wen 22 5000 人事部 emp.objects.values('dep').annotate(c=Count('*')) values(‘dep')就是按‘dep'進(jìn)行分組 annotate()對(duì)每個(gè)分組的進(jìn)行操作
2.2 多表分組查詢
每一個(gè)出版社的名稱和出版過的書籍個(gè)數(shù) Publish.objects.values('name').annotate(c=Count('book')) #首先讀整個(gè)語(yǔ)句,當(dāng)讀到‘book'時(shí),就會(huì)把兩個(gè)表連起來,然后在按Publish.name分組 跨表分組查詢本質(zhì)就是將關(guān)聯(lián)表join成一張表,然后再按單表的思路進(jìn)行分組查詢 還有一種寫法: publishlist=Publish.objects.annotate(c=Count('book')) 這相當(dāng)于給Publish表添加了一個(gè)‘c'字段。首先也是把兩張表連起來,以Publish分組,計(jì)算每個(gè)Publish的書籍?dāng)?shù)量 publishlist是一個(gè)queryset對(duì)象集合,里面放的是publish模型類對(duì)象,只是現(xiàn)在的對(duì)象比之前多了一個(gè)‘c'字段 for publish in publishlist: print(publish.name,publish.c) 利用for循環(huán)就可以遍歷出每個(gè)模型類對(duì)象,然后用句點(diǎn)符‘.'就可以取得任何字段的值 我們也可以不用for循環(huán),直接用values_list()就可以實(shí)現(xiàn),如上面的for循環(huán)可以寫成:values_list('name','c') 統(tǒng)計(jì)每一本書的作者個(gè)數(shù) Book.objects.annotate(c=Count('author')).values_list('name','c') filter()放在annotate()前面就是相當(dāng)于where 統(tǒng)計(jì)每一本以py開頭的書籍的作者的個(gè)數(shù): Book.objects.filter(name__startswith='py').annotate(c=Count('author')).values_list('name','c') filter()放在annotate()后面就相當(dāng)于having 統(tǒng)計(jì)作者個(gè)數(shù)大于1的書籍: Book.objects.annotate(c=Count('author')).filter(c__gt=1).value_list('name','c') 根據(jù)書籍的作者數(shù)來排序: Book.objects.annotate(c=Count('author')).orderby('c')
六、F查詢與Q查詢
1,F(xiàn)查詢
在之前,對(duì)象的字段只能放在比較符的前面,比如filter(id__gt=2),但現(xiàn)在,有一個(gè)表,有生物成績(jī)ss字段和物理成績(jī)ws字段,統(tǒng)計(jì)物理成績(jī)高于生物成績(jī)的學(xué)生: student.objects.filter(ws__gt=ss) 這樣寫肯定是報(bào)錯(cuò)的,因?yàn)樽侄螌懺诹吮容^符后面,但此時(shí)我們借助F查詢就可以不報(bào)錯(cuò)了,正確寫法如下: student.objcts.filter(ws__gt=F('ss')) F('ss')此時(shí)就是把ss字段的值取出來,就相當(dāng)于一個(gè)純數(shù)字了,可以進(jìn)行加減乘除操作 查詢物理成績(jī)大于生物成績(jī)兩倍的學(xué)生 student.objects.filter(ws__gt=F('ss')*2) 把每個(gè)學(xué)生的物理成績(jī)加上10分: student.objects.all().update(ws=F('ws')+10)
2,Q查詢
之前我們?cè)谟胒ilter()時(shí),可以用‘,'表示與關(guān)系,但沒有或關(guān)系,現(xiàn)在我們用Q查詢就可以實(shí)現(xiàn)或關(guān)系 Book.objects.filter(Q(id__gt=2)|Q(title__startswith='p')) 過濾出id大于2或者以‘p'開頭的 Book.objects.filter(Q(id__gt=2)&Q(title__startswith='p')) 過濾出id大于2且以‘p'開頭的 Book.objects.filter(Q(id__gt=2)|~Q(title__startswith='p')) 過濾出id大于2或不以‘p'開頭的 Q查詢可以和關(guān)鍵字參數(shù)混用,但Q()在前面 Book.objects.filter(Q(pub_date__year=2017)|Q(pub_date__year=2016),pub_date__month=2)過濾出2017年2月份或2016年2月份的書籍
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。