日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

九、多表模型创建,一对一,一对多,基于对像的多表模型等

發(fā)布時間:2024/4/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 九、多表模型创建,一对一,一对多,基于对像的多表模型等 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

環(huán)境:

django1.9環(huán)境:

settings.py,注釋csrf,并且設置使用mysql數據庫

數據庫的對應關系圖:

一、多表模型創(chuàng)建,一對多增刪改查,多對多增刪改查

一對多:

models.py

總結:

#用了OneToOneField和ForeignKey,模型表的字段,后面會自定加_id
# ManyToManyField會自動創(chuàng)建第三張表
# *************重點
# 一對一的關系:OneToOneField
# 一對多的關系:ForeignKey
# 多對多的關系:ManyToManyField

# id如果不寫,會自動生成,名字叫nid,并且自增(數據庫類型不同,生成的名字也會隨之不同)

from?django.db?import?models#?Create?your?models?here. class?Publish(models.Model):id?=?models.AutoField(primary_key=True)name?=?models.CharField(max_length=32)addr?=?models.CharField(max_length=64)email?=?models.EmailField()class?AuthorDetail(models.Model):id?=?models.AutoField(primary_key=True)phone?=?models.CharField(max_length=32)addr?=?models.CharField(max_length=64)class?Author(models.Model):id?=?models.AutoField(primary_key=True)name?=?models.CharField(max_length=16)#?數字類型sex?=?models.IntegerField()#?#?to='AuthorDetail'??加引號,這個表能找到就可以,不用引號,類必須在上面定義authordetail?=?models.OneToOneField(to='AuthorDetail',?to_field='id')def?__str__(self):return?self.nameclass?Book(models.Model):id?=?models.AutoField(primary_key=True)name?=?models.CharField(max_length=32)price?=?models.DecimalField(max_digits=5,?decimal_places=2)publish?=?models.ForeignKey(to=Publish,?to_field='id')authors?=?models.ManyToManyField(to=Author)def?__str__(self):return?self.name

python3 manage makemigrations
python3 manage migrate

二、添加表記錄

在11-13數據庫中的app01_publish表中添加出版社數據:

在項目的根下添加test.py文件

import?os if?__name__?==?'__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE",?"pro11_13.settings")import?djangodjango.setup()from?app01.models?import?*#?以上代碼是屬于如何讓py文件在django環(huán)境中運行?#?一對多新增數據#?添加一本北京出版社出版的書#?第一種方式ret=Book.objects.create(name='紅樓夢',price=34.5,publish_id=1)print(ret.name)#?紅樓夢

然后在book表中就會出先之前插入的數據。


import?osif?__name__?==?'__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE",?"pro11_13.settings")import?djangodjango.setup()from?app01.models?import?*#?第二種方式,存對象publish=出版社的對象,存到數據庫,是一個idpublish=Publish.objects.filter(pk=2).first()ret?=?Book.objects.create(name='西游記',?price=34.5,?publish=publish)print(ret.name)#?西游記

一對一修改數據:

方式一:

book=Book.objects.get(pk=1) book.publish=出版社對象 book.publish_id=2 book.save()

方式二:

book=Book.objects.filter(pk=1).update(publish=出版社對象) #?book=Book.objects.filter(pk=1).update(publish_id=1)

多對多新增:

首先在數據中添加作者與作者詳情

# 為紅樓夢這本書新增一個叫l(wèi)qz,egon的作者

方式一:

lqz=Author.objects.filter(name='lqz').first() egon=Author.objects.filter(name='egon').first() book=Book.objects.filter(name='紅樓夢').first() #?add?添加多個對象 book.authors.add(lqz,egon

方式二:(為了測試,先把app01_book_authors表中的數據全部刪除)

book=Book.objects.filter(name='紅樓夢').first() book.authors.add(1,2)

多對多刪除:

方式一:

# remove,可以傳對象,可以傳id,可以傳多個,不要混著用

lqz=Author.objects.filter(name='lqz').first() book=Book.objects.filter(name='紅樓夢').first() book.authors.remove(lqz)

方式二:

lqz=Author.objects.filter(name='lqz').first() egon=Author.objects.filter(name='egon').first() book=Book.objects.filter(name='紅樓夢').first() book.authors.remove(1) #?book.authors.remove(1,2) #?clear清空所有 #?book.authors.clear()

多對多修改:

# ?set,先清空,在新增,要傳一個列表,列表內可以是, id,也可以是對象

原來表中的數據:


lqz=Author.objects.filter(name='lqz').first() egon=Author.objects.filter(name='egon').first() book=Book.objects.filter(name='紅樓夢').first() book.authors.set([2,]) #?或者: #?book.authors.set([lqz,])

修改之后:

錯誤方式:

********這樣不行,因為它打散了傳過去了,相當于book.authors.set(lqz) #?book.authors.set(*[lqz,])

總結:

添加表記錄
?? ??? ?1 一對多新增
?? ??? ??? ?-兩種方式:
?? ??? ??? ??? ?-publish=對象
?? ??? ??? ??? ?-publish_id=id
?? ??? ?2 一對多刪除:同單表刪除
?? ??? ?3 一對多修改:兩種方式,可以傳對象,可以傳id
?? ??? ?4 一對一跟一對多一樣
?? ??? ?5 多對多:
?? ??? ??? ?-add? ----->可以傳對象,可以傳id,可以傳多個
?? ??? ??? ?-remove? ----->可以傳對象,可以傳id,可以傳多個
?? ??? ??? ?-clear? ---->沒有參數
?? ??? ??? ?-set?? ----->跟上面不一樣,必須傳列表,列表里面可以是對象,可以是id

三、基于對象的跨表查詢,一對一,一對多,多對多查詢

????????1 一對一
?? ??? ??? ?正向:正向查詢按字段,(author---關聯字段在author--->authordetail?? ------>? 按字段)

?? ??? ???? ?# 查詢egon作者的手機號?? 正向查詢

author=Author.objects.filter(name='egon').first() authordetail=author.authordetail print(authordetail.phone) --------------------------------- 13513513561

????????????反向:反向查詢按表名小寫,(authordetail------關聯字段在author--->author? -----> 按表名小寫)

????????????#? 查詢地址是 :山東 的作者名字?? 反向查詢

authordetail=AuthorDetail.objects.filter(addr='?上海').first() author?=?authordetail.author print(author.name) ---------------------------- egon

?? ???? 2 一對多
?? ??? ??? ?正向:正向查詢按字段。(拿書查出版社信息)

????????????正向?? book---關聯字段在book--->publish?? ------>? 按字段

????????????正向 查詢紅樓夢這本書的出版社郵箱

book=Book.objects.filter(name='紅樓夢').first() pulish=book.publish print(pulish.email) ------------------- 564@qq.com


?? ??? ???? 反向:反向按表名小寫_set.all()

????????????反向?? publish------關聯字段在book--->book? -----> 按表名小寫_set.all()(拿出版社信息查詢圖書)。

????????????反向? 查詢地址是北京 的出版社出版的圖書

publish=Publish.objects.filter(addr='北京').first() books=publish.book_set.all()??#?publish.book_set.all()??拿出所有的圖書 print(books) -------------------- <QuerySet?[<Book:?紅樓夢>]> #?統(tǒng)計一下條數 books=publish.book_set.all().count() print(books) ----------------- 1

?? ???? 3 多對多
?? ??? ??? ?正向:正向查詢按字段

????????????正向?? book---關聯字段在book--->author?? ------>? 按字段.all()

????????????#查詢紅樓夢這本書所有的作者

book=Book.objects.filter(name='紅樓夢').first() print(book.authors.all())???#?是所有的作者,是一個queryset對象,可以繼續(xù)點 --------------------------------------------- <QuerySet?[<Author:?egon>]>

?? ??? ???? 反向查詢:反向按表名小寫_set.all()

????????????反向?? author------關聯字段在book--->book? -----> 按表名小寫_set.all()

????????????# 查詢lqz寫的所有書

egon=Author.objects.filter(name='egon').first() books=egon.book_set.all() print(books) ------------------------------------------------------ <QuerySet?[<Book:?紅樓夢>]>

?# 連續(xù)跨表
?# 查詢紅樓夢這本書所有的作者的手機號

book=Book.objects.filter(name='紅樓夢').first() authors=book.authors.all()for?author?in?authors:authordetail=author.authordetailprint(authordetail.phone) ----------------------------------------- 13513513561

四、******基于對象的查詢,是子查詢也就是多次查詢)

*********************基于雙下劃線的查詢***************

# 一對一
# 查詢lqz作者的手機號?? 正向查詢? 跨表的話,按字段
# 以author表作為基表

ret=Author.objects.filter(name='egon').values('authordetail__phone') print(ret) ------------------------------ <QuerySet?[{'authordetail__phone':?'13513513561'}]>

# 以authordetail作為基表

# 反向查詢,按表名小寫? 跨表的話,用表名小寫

ret=AuthorDetail.objects.filter(author__name='egon').values('phone') print(ret) --------------------------------------------- <QuerySet?[{'phone':?'13513513561'}]>

# 查詢lqz這個作者的性別和手機號
# 正向

ret=Author.objects.filter(name='egon').values('sex','authordetail__phone') print(ret) ------------------------- <QuerySet?[{'sex':?1,?'authordetail__phone':?'13513513561'}]>


# 查詢手機號是13513513561的作者性別

ret=Author.objects.filter(authordetail__phone='13513513561').values('sex') print(ret) ------------------------------------- <QuerySet?[{'sex':?1}]>ret=AuthorDetail.objects.filter(phone='13513513561').values('author__sex') print(ret) ------------------------- <QuerySet?[{'author__sex':?1}]>

五、基于雙下劃線的一對多查詢

#?查詢出版社為北京出版社出版的所有圖書的名字,價格 ret=Publish.objects.filter(name='北京出版社').values('book__name','book__price') print(ret) ---------------------------------------------------------------------- <QuerySet?[{'book__name':?'紅樓夢',?'book__price':?Decimal('34.50')},?{'book__name':?'西游記',?'book__price':?Decimal('553.30')}]> ------------------------------------------------------------------------ ret=Book.objects.filter(publish__name='北京出版社').values('name','price') print(ret) ----------------------------------------------------- <QuerySet?[{'name':?'紅樓夢',?'price':?Decimal('34.50')},?{'name':?'西游記',?'price':?Decimal('553.30')}]>#?反向查詢 #?查詢北京出版社出版的價格大于19的書 ret=Publish.objects.filter(name='北京出版社',book__price__gt=19).values('book__name','book__price') print(ret) ----------------------------------------------------- <QuerySet?[{'book__name':?'紅樓夢',?'book__price':?Decimal('34.50')},?{'book__name':?'西游記',?'book__price':?Decimal('553.30')}]>

六、基于雙下劃線的多對多查詢

#?查詢紅樓夢的所有作者名字 ret=Book.objects.filter(name='紅樓夢').values('authors__name') print(ret) -------------------------- <QuerySet?[{'book__name':?'紅樓夢',?'book__price':?Decimal('34.50')},?{'book__name':?'西游記',?'book__price':?Decimal('553.30')}]> ----------------------------------------------------------- ret=Author.objects.filter(book__name='紅樓夢').values('name') print(ret) ------------------------------------------------------------------ <QuerySet?[{'name':?'egon'}]> #?查詢圖書價格大于30的所有作者名字 ret=Book.objects.filter(price__gt=30).values('authors__name') print(ret) --------------------------------- <QuerySet?[{'authors__name':?'egon'},?{'authors__name':?None}]> #?進階練習--連續(xù)跨表#?查詢北京出版社出版過的所有書籍的名字以及作者的姓名 ret=Publish.objects.filter(name='北京出版社').values('book__name','book__authors__name') print(ret) ---------------------------------------- <QuerySet?[{'book__name':?'紅樓夢',?'book__authors__name':?'egon'},?{'book__name':?'西游記',?'book__authors__name':?None}]> ---------------------------------------------------------- ret=Book.objects.filter(publish__name='北京出版社').values('name','authors__name') print(ret) --------------------------------------- <QuerySet?[{'name':?'紅樓夢',?'authors__name':?'egon'},?{'name':?'西游記',?'authors__name':?None}]>#?手機號以135開頭的作者出版過的所有書籍名稱以及出版社名稱 ret=AuthorDetail.objects.filter(phone__startswith='135').values('author__book__name','author__book__publish__name') print(ret) -------------------------------------------------- <QuerySet?[{'author__book__name':?'紅樓夢',?'author__book__publish__name':?'北京出版社'}]> --------------------------------------------------------------------- ret=Book.objects.filter(authors__authordetail__phone__startswith='135').values('name','publish__name') print(ret) ----------------------------------------------------------------------- <QuerySet?[{'name':?'紅樓夢',?'publish__name':?'北京出版社'}]>

# 聚合查詢aggregate

from?django.db.models?import?Avg,Count,Max,Min,Sum #?計算所有圖書的平均價格 ret=Book.objects.all().aggregate(Avg('price')) print(ret) ----------------------- {'price__avg':?293.9}#??計算圖書的最高價格 ret=Book.objects.all().aggregate(Max('price')) print(ret) ------------------------------------ {'price__max':?Decimal('553.30')}#他是queryset的終止子句 #?計算圖書的最高價格,最低價格,平均價格,總價 ret=Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price')) print(ret) --------------------------------------------- {'price__max':?Decimal('553.30'),?'price__min':?Decimal('34.50'),?'price__avg':?293.9,?'price__sum':?Decimal('587.80')}#?分組查詢annotate() #?統(tǒng)計每一本書作者個數 ret=Book.objects.all().annotate(c=Count('authors')) print(ret) for?r?in?ret:print(r.name,'---->',r.c) ---------------------------------------------- <QuerySet?[<Book:?紅樓夢>,?<Book:?西游記>]> 紅樓夢?---->?1 西游記?---->?0 --------------------------------------------- ret=Book.objects.all().annotate(c=Count('authors')).values('name','c') print(ret) ------------------------------------ <QuerySet?[{'name':?'紅樓夢',?'c':?1},?{'name':?'西游記',?'c':?0}]>#?統(tǒng)計每一個出版社的最便宜的書(以誰group?by?就以誰為基表) ret=Publish.objects.all().annotate(m=Min('book__price')).values('name','m') print(ret) ------------------------------------------ <QuerySet?[{'name':?'北京出版社',?'m':?Decimal('34.50')}]> #?統(tǒng)計每一本以py開頭的書籍的作者個數 ret=Book.objects.all().filter(name__startswith='py').annotate(c=Count('authors')).values('name','c') print(ret) -------------------------------- <QuerySet?[{'name':?'py書大全',?'c':?0}]>#?總結:??group?by?誰,就以誰做基表,filter過濾,annotate取分組,values取值#?總結終極版本#?values在前,表示group?by?在后,表示取值#?filter在前,表示where條件,在后表示having#?統(tǒng)計每一本以py開頭的書籍的作者個數--套用模板 ret=Book.objects.all().values('name').filter(name__startswith='py').annotate(c=Count('authors')).values('name','c') print(ret) ----------------------------------- <QuerySet?[{'name':?'py書大全',?'c':?0}]>#?查詢各個作者出的書的總價格 ret=Author.objects.all().values('name').annotate(s=Sum('book__price')).values('name','s') print(ret) -------------------------------------------------------- <QuerySet?[{'name':?'egon',?'s':?Decimal('34.50')}]>ret=Author.objects.all().annotate(s=Sum('book__price')).values('name','s') print(ret) ---------------------------------------------------------- <QuerySet?[{'name':?'egon',?'s':?Decimal('34.50')}]>#?查詢名字叫egon作者書的總價格 ret=Author.objects.all().values('pk').filter(name='egon').annotate(s=Sum('book__price')).values('name','s') print(ret) ----------------------------------- <QuerySet?[{'name':?'egon',?'s':?Decimal('34.50')}]>#?查詢所有作者寫的書的總價格大于30 ret=Author.objects.all().values('pk').annotate(s=Sum('book__price')).filter(s__gt=2).values('name','s') print(ret) ----------------------------------------- <QuerySet?[{'name':?'egon',?'s':?Decimal('34.50')}]>ret=Author.objects.all().annotate(s=Sum('book__price')).filter(s__gt=30).values('name','s') print(ret) ------------------------------------------- <QuerySet?[{'name':?'egon',?'s':?Decimal('34.50')}]>#?總結終極版本 #?values在前,表示group?by?在后,表示取值 #?filter在前,表示where條件,在后表示having#?統(tǒng)計不止一個作者的圖書 ret?=?Book.objects.annotate(author_num=Count("authors")).filter(author_num__gt=1).values('name','author_num') ret=Book.objects.all().values('pk').annotate(c=Count('authors')).filter(c__gt=1).values('name','c') print(ret)

七、F函數

models.py

from?django.db?import?models#?Create?your?models?here.#用了OneToOneField和ForeignKey,模型表的字段,后面會自定加_id #?ManyToManyField會自動創(chuàng)建第三張表 #?*************重點 #?一對一的關系:OneToOneField #?一對多的關系:ForeignKey #?多對多的關系:ManyToManyFieldclass?Publish(models.Model):#?id如果不寫,會自動生成,名字叫nid,并且自增id?=?models.AutoField(primary_key=True)name?=?models.CharField(max_length=32)addr?=?models.CharField(max_length=64)email?=?models.EmailField()class?Author(models.Model):id?=?models.AutoField(primary_key=True)name?=?models.CharField(max_length=32)#?數字類型sex?=?models.IntegerField()#?可以用ForeignKey,但是得設置唯一性約束,會報警告,不建議用,建議用OneToOneField#?authordetail=models.ForeignKey(unique=True)#?to='AuthorDetail'??加引號,這個表能找到就可以,不用引號,類必須在上面定義authordetail?=?models.OneToOneField(to='AuthorDetail',?to_field='id')def?__str__(self):return?self.nameclass?AuthorDetail(models.Model):id?=?models.AutoField(primary_key=True)phone?=?models.CharField(max_length=32)addr?=?models.CharField(max_length=64)class?Book(models.Model):id?=?models.AutoField(primary_key=True)name?=?models.CharField(max_length=32,db_index=True)price?=?models.DecimalField(max_digits=5,?decimal_places=2)#?閱讀數reat_num=models.IntegerField(default=0)#?評論數commit_num=models.IntegerField(default=0)publish?=?models.ForeignKey(to=Publish,?to_field='id',on_delete=models.CASCADE)authors?=?models.ManyToManyField(to=Author)#?test=models.PositiveSmallIntegerField()def?__str__(self):return?self.nameclass?Test(models.Model):name=models.CharField(max_length=32)class?Meta:db_table='aaa'

python3 manage makemigrations
python3 manage migrate

import?osif?__name__?==?'__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE",?"day77.settings")import?djangodjango.setup()from?app01.models?import?* from?django.db.models?import?F #?查詢評論數大于閱讀數的書 ret=Book.objects.all().filter(commit_num__gt=F('reat_num')) print(ret) --------------------------------- <QuerySet?[<Book:?紅樓夢>]>#?把所有書的評論數加100 ret=Book.objects.all().update(commit_num=F("commit_num")+100) print(ret)#?把紅樓夢這本書的閱讀數減5 ret?=?Book.objects.all().filter(name='紅樓夢').update(reat_num=F('reat_num')?-?5) print(ret)#?Q函數?為了表示與&?,或?|?,非?~, from?django.db.models?import?Q #?查詢作者不是lqz的書 ret=Book.objects.filter(~Q(authors__name='lqz')) print(ret) <QuerySet?[<Book:?紅樓夢>,?<Book:?西游記>,?<Book:?py書大全>]> #?????構建很復雜的邏輯,需要用括號來區(qū)分 ret?=?Book.objects.filter((Q(name='紅樓夢')?&?Q(price__gt=100))?|?Q(pk__gt=2)) print(ret) ------------------------------ <QuerySet?[<Book:?py書大全>]>

總結:

1基于雙下劃線的跨表查詢套路一樣,用__跨表-一對多-多對多2?聚合查詢-聚合函數from?django.db.models?import?Avg,Count,Max,Min,Sum#?計算所有圖書的平均價格#?ret=Book.objects.all().aggregate(Avg('price'))#?print(ret)3分組查詢終極總結:values在前,表示group?by,在后,表示取值filter在前,表示過濾(where),在后,表示having(對分組之后的結果再進行過濾)4?F查詢與Q查詢-F為了字段=后面的值,不能放字段,所以用F函數包裹一下就可以了-Q為了構造與&,或|,非~的關系5?常用字段:必須記住,非常用字段,了解即可6?orm字段參數:-null??可以為空-unique??唯一性約束-default?默認值-db_index?為該字段建索引-只給日期類型和時間類型用-auto_now_add????新增數據時,默認把當前時間存入-auto_now????????修改的時候,默認把當前時間存入7?關系字段ForeignKey-to??關聯哪個表-to_field?關聯的字段-related_name?反向操作時,使用的字段名,用于代替原反向查詢時的'表名_set'。(一般不要用)-related_query_name?:基于雙下劃線的反向查詢之前按表名小寫(一般不要用)-on_delete:models.CASCADE,models.SET_NULL-db_constraint:db_constraint=False代表,不做外鍵關聯作業(yè):1?手動創(chuàng)建第三張表,并且新增,刪除,查詢數據2?整理博客3?上課講的敲一遍



轉載于:https://blog.51cto.com/silencezone/2361369

總結

以上是生活随笔為你收集整理的九、多表模型创建,一对一,一对多,基于对像的多表模型等的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。