最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Django ORM、一對一、一對多、多對多的全面講解

 更新時間:2019年07月26日 10:19:30   作者:青春永不言棄  
今天小編就為大家分享一篇基于Django ORM、一對一、一對多、多對多的全面講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

上篇博客也提到這些知識點,可能大家還是不太清楚,這篇博客為大家詳細講解ORM中的幾個知識點

1.1首先我們先看一個小案例:

#_*_coding:utf-8_*_
from django.db import models
 
# Create your models here.
 
class Colors(models.Model):
 colors=models.CharField(max_length=10) #藍色
 def __str__(self):
  return self.colors
 
class Ball(models.Model):
 color=models.OneToOneField("Colors") #與顏色表為一對一,顏色表為母表
 description=models.CharField(max_length=10) #描述
 def __str__(self):
  return self.description
 
class Clothes(models.Model):
 color=models.ForeignKey("Colors") #與顏色表為外鍵,顏色表為母表
 description=models.CharField(max_length=10) #描述
 def __str__(self):
  return self.description 
  
class Child(models.Model):
 name=models.CharField(max_length=10) #姓名 
 favor=models.ManyToManyField('Colors') #與顏色表為多對多
 

先來區(qū)分一下什么是一對一、多對多

一對一:子表從母表中選出一條數(shù)據(jù)一一對應,母表中選出來一條就少一條,子表不可以再選擇母表中已被選擇的那條數(shù)據(jù)

一對多:子表從母表中選出一條數(shù)據(jù)一一對應,但母表的這條數(shù)據(jù)還可以被其他子表數(shù)據(jù)選擇

共同點是在admin中添加數(shù)據(jù)的話,都會出現(xiàn)一個select選框,但只能單選,因為不論一對一還是一對多,自己都是“一”

多對多總結:

比如有多個孩子,和多種顏色、

每個孩子可以喜歡多種顏色,一種顏色可以被多個孩子喜歡,對于雙向均是可以有多個選擇

應用場景

一對一:一般用于某張表的補充,比如用戶基本信息是一張表,但并非每一個用戶都需要有登錄的權限,不需要記錄用戶名和密碼,此時,合理的做法就是新建一張記錄登錄信息的表,與用戶信息進行一對一的關聯(lián),可以方便的從子表查詢母表信息或反向查詢

外鍵:有很多的應用場景,比如每個員工歸屬于一個部門,那么就可以讓員工表的部門字段與部門表進行一對多關聯(lián),可以查詢到一個員工歸屬于哪個部門,也可反向查出某一部門有哪些員工

多對多:如很多公司,一臺服務器可能會有多種用途,歸屬于多個產品線當中,那么服務器與產品線之間就可以做成對多對,多對多在A表添加manytomany字段或者從B表添加,效果一致

一對一

查:

#子表查詢母表,找到紅球對應的顏色
#寫法1:
print(models.Ball.objects.get(description="紅球").color.colors) #返回紅,通過子表查詢母表,寫法:"子表對象.母表表名的小寫.母表字段名" ;通過Ball表查到description為"紅球",查找到對應colors
#寫法2,反向從母表入手:
print(models.Colors.objects.get(ball__description="紅球").colors) #返回紅,通過子表查詢母表,但形式上是從母表對象自身直接獲取字段,寫法:"母表.objects.get(子表名小寫__子表字段="xxx").母表字段名" ;效果和上邊完全一致,另一種形式


#母表查詢子表,找到紅色對應的球的名字
#寫法1:
print(models.Colors.objects.get(colors="紅").ball.description) #返回紅球,通過母表查詢子表,寫法:"母表對象.子表表名的小寫.子表字段名";找到顏色為紅色的Ball的description
#寫法2,反向從子表入手:
print(models.Ball.objects.get(color__colors="紅").description) #返回紅球,通過母表查詢子表,但形式上是從子表對象自身直接獲取字段,寫法:"子表.objects.get(一對一的子表字段__母表字段="xxx").子表字段";效果和上邊完全一致,另一種形式

增:

#添加一種顏色黑,并添加黑球
color_obj=models.Colors.objects.create(colors="黑") #先在母表中創(chuàng)建顏色,并實例化給顏色表對象
models.Ball.objects.create(color=color_obj,description="黑球") #更新Ball表,color字段為顏色表對象,添加description字段

備注:增添數(shù)據(jù)的3種常用方式

#增添數(shù)據(jù)的三種寫法:
#寫法1:
color_obj=models.Colors.objects.create(colors="黑")
models.Ball.objects.create(color=color_obj,description="黑球")
#寫法1補充:
color_id=models.Colors.objects.create(colors="黑").id
models.Ball.objects.create(color_id=color_id,description="黑球")
#寫法2:
color_obj=models.Colors.objects.create(colors="黑")
ball_obj=models.Ball(color=color_obj,description="黑球")
ball_obj.save()
#寫法3(字典導入):
color_obj=models.Colors.objects.create(colors="黑")
ball_dic={'description':"黑球"}
models.Ball.objects.create(color=color_obj,**ball_dic)

改:

color_obj=models.Colors.objects.get(colors="黑") #.get()等同于.filter().first()
color_obj.colors="灰"
color_obj.save()
models.Ball.objects.filter(description="黑球").update(color=color_obj,description="灰球") #update(),delete()是QuerySet的方法

備注:修改數(shù)據(jù)的常見方式

#更新一條數(shù)據(jù)
color_obj=models.Colors.objects.get(colors="黑")
color_obj.colors="灰"
color_obj.save()
#更新多條數(shù)據(jù),把滿足條件的球的description都變?yōu)榛仪?
#寫法1:
models.Ball.objects.filter(color__colors="紅").update(description="灰球")
#寫法2:
up_dic={"description":"灰球"}
models.Ball.objects.filter(id__gt=0).update(**up_dic)

刪:

models.Ball.objects.get(description="灰球").delete() #對象和QuerySet都有方法delete()
models.Colors.objects.filter(colors="灰").delete()

models.Colors.objects.all().delete() #清空一張表

一對多(外鍵)

查:

#外鍵表聯(lián)合查詢:

#外鍵子表查詢母表,與一對一子表查詢母表形式一致
#找到紅褲衩所屬的顏色表中的顏色--返回:紅
#寫法1:
print(models.Clothes.objects.get(description="小虎哥").color.colors) #返回紅,通過子表查詢母表,寫法:"子表對象.母表表名的小寫.母表字段名" ;通過Clothes表查到description為"小虎哥",查找到對應colors
#寫法2,反向從母表入手:
print(models.Colors.objects.get(clothes__description="小虎哥").colors) #返回紅,通過子表查詢母表,但形式上是從母表對象自身直接獲取字段,寫法:"母表.objects.get(子表名小寫__子表字段="xxx").母表字段名" ;效果和上邊完全一致,另一種形式

#外鍵母表查詢子表,與一對一形式不同,因為母表為"多",不能像一對一一樣通過.get().子表.子表字段的方式獲取,但與多對多母表查詢子表一致
#找到顏色為紅的所有服裝--返回:[<Clothes: 大美女>, <Clothes: 小虎哥>]
#寫法1:
color_obj=models.Colors.objects.get(colors="紅")
print(color_obj.clothes_set.all()) #注意:子表小寫_set的寫法,它實際上是一個QuerySet,可以用update,delete,all,filter等方法
#寫法2:
print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="紅")))
#寫法2簡便寫法(推薦):
print(models.Clothes.objects.filter(color__colors="紅")) #寫法:filter(子表外鍵字段__母表字段='過濾條件')
#寫法3:
color_id=models.Colors.objects.get(colors="紅").id #通過母表獲取到顏色為紅的id
print(models.Clothes.objects.filter(color_id=color_id)) #filter得到QuerySet,寫法:filter(子表外鍵字段_母表主鍵=母表主鍵對象)

備注:通過QuerySet的.values()方法,將QuerySet轉化為ValuesQuerySet

print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="紅")).values('color__colors','description')) #獲取子表的description字段,和母表的colors字段,獲取母表字段寫法: 子表外鍵字段名__母表字段名--適用于values()或filter()
#簡寫形式補充:
print(models.Clothes.objects.filter(color__colors="紅").values('color__colors','description'))
#返回:
[{'description': u'\u7ea2\u5185\u8863', 'color__colors': u'\u7ea2'}, {'description': u'\u7ea2\u5185\u88e4', 'color__colors': u'\u7ea2'}]
#如果不加values(),返回的是[<Clothes: 大美女>, <Clothes: 小虎哥>]這樣一個QuerySet集合,通過values可以形成一個列表,列表中的每一個元素是一個字典,可以通過list()將ValuesQeurySet轉化為列表,之后返回給templates


#另外可通過.values_list()將QuerySet轉化為ValuesListQuerySet。返回:[(u'\u7ea2', u'\u7ea2\u889c\u5b50'), (u'\u7ea2', u'\u7ea2\u889c\u5b50')]
#得到的是一個列表,列表中是多個元組,每個元組是ValuesQuerySet中字典的value,常用于從models里將數(shù)據(jù)取出后動態(tài)添加到前端模板中的select選項中。
#通過forms.py從models取值傳給前端select選項,需重啟django后,select選項才能更新,可在定義form時,添加如下關鍵字保障動態(tài)更新select選項
#forms.py
from django import forms
from test1 import models
class ClothesForm(forms.Form):
 color=forms.IntegerField(required=True,widget=forms.Select(),)
 def __init__(self,*args,**kwargs): #定義這個關鍵字段,當使用form時,colors表新增了顏色,前端ClothesForm的color字段的選項會自動更新
  super(ClothesForm, self).__init__(*args,**kwargs)
  self.fields['color'].widget.choices=models.Colors.objects.all().order_by('id').values_list('id','colors')

增:

#增添子表數(shù)據(jù),形式與一對一一致
#添加顏色為綠的服裝:小帥哥
#方法1:
models.Clothes.objects.create(color=models.Colors.objects.get(colors="綠"),description="小帥哥")
#方法1補充:
models.Clothes.objects.create(color_id=models.Colors.objects.get(colors="綠").id,description="小帥哥")
#方法2:
c_obj=models.Clothes(color=models.Colors.objects.get(colors="綠"),description="小帥哥")
c_obj.save()
#方法3:字典方式錄入..參考一對一

改:

#顏色為紅的服裝,description都更新為大美女
#寫法1:
models.Clothes.objects.filter(color__colors="紅").update(description="大美女")
#寫法2:
models.Clothes.objects.filter(color_id=models.Colors.objects.get(colors="紅").id).update(description="大美女")
#寫法3:
colors_obj=models.Colors.objects.get(colors="紅")
colors_obj.clothes_set.filter(id__gte=1).update(description="大美女")
#其他寫法參照一對一的修改和外鍵的查詢

刪:

models.Clothes.objects.get(description="灰裙子").delete() #對象和QuerySet都有方法delete()
models.Colors.objects.filter(colors="灰").delete()

多對多

查:

#多對多子表查詢母表,查找小明喜歡哪些顏色--返回:[<Colors: 紅>, <Colors: 黃>, <Colors: 藍>]
#與一對多子表查詢母表的形式不同,因為一對多,查詢的是母表的“一”;多對多,查詢的是母表的“多”
#寫法1:
child_obj=models.Child.objects.get(name="小明") #寫法:子表對象.子表多對多字段.過濾條件(all()/filter())
print(child_obj.favor.all())
#寫法2,反向從母表入手:
print(models.Colors.objects.filter(child__name="小明")) #母表對象.filter(子表表名小寫__子表字段名="過濾條件")


#多對多母表查詢子表,查找有哪些人喜歡黃色--返回:[<Child: 小明>, <Child: 丫蛋>]
#與一對多母表查詢子表的形式完全一致,因為查到的都是QuerySet,一對多和多對多,都是在查詢子表的“多”
#寫法1:
color_obj=models.Colors.objects.get(colors="黃")
print(color_obj.child_set.all())
#寫法2:
print(models.Child.objects.filter(favor=models.Colors.objects.get(colors="黃")))
#寫法2簡便寫法(推薦):
print(models.Child.objects.filter(favor__colors="黃")) #寫法:filter(子表外鍵字段__母表字段='過濾條件')
#寫法3:
color_id=models.Colors.objects.get(colors="黃").id #通過母表獲取到顏色為紅的id
print(models.Child.objects.filter(favor=color_id)) #filter得到QuerySet,寫法:filter(子表外鍵字段=母表主鍵對象),此處和一對多略有不同,是子表外鍵字段而不是外鍵字段_母表主鍵

增與改(增添子表或母表數(shù)據(jù)參照一對一的增,多對多重點在于關系表的對應關系變更):

#添加子表關聯(lián)關系
#添加小虎并讓他喜歡所有顏色
#寫法1:
child_obj=models.Child.objects.create(name="小虎") #如果是已有用戶,使用.get()
colors_obj=models.Colors.objects.all() #創(chuàng)建顏色表的所有顏色QuerySet對象
child_obj.favor.add(*colors_obj) #添加對應關系,將小虎和所有顏色進行關聯(lián),寫法:子表對象.子表多對多字段.add(*QuerySet對象)
#寫法2:
child_obj=models.Child.objects.get(name="小虎")
colors_obj=models.Colors.objects.all()
child_obj.favor=colors_obj
child_obj.save()
#讓小虎喜歡黃色和藍色(2種寫法和上邊一致,只展示一種寫法)
child_obj=models.Child.objects.get(name="小虎")
colors_obj=models.Colors.objects.filter(colors__in=["藍","黃"]) #models默認只能用這種方式得到并集,如需更復雜的過濾邏輯,需使用模塊Q
child_obj.favor.clear() #清空小虎已經喜歡的顏色
child_obj.favor.add(*colors_obj) #add是追加模式,如果當前小虎已經喜歡綠色,那么執(zhí)行后,小虎會額外喜歡藍,黃
#讓小虎喜歡綠色(2種寫法和上邊一致,只展示一種寫法)
child_obj=models.Child.objects.get(name="小虎")
colors_obj=models.Colors.objects.get(colors="綠")
child_obj.favor.clear()
child_obj.favor.add(colors_obj) #此處沒有*


#添加母表關聯(lián)關系
#讓喜歡藍色的人里添加小虎,可以用上邊的方法,一個效果,讓小虎喜歡藍色,下邊介紹反向插入(從母表入手)的寫法
child_obj=models.Child.objects.get(name="小虎")
colors_obj=models.Colors.objects.get(colors="藍")
colors_obj.child_set.add(child_obj) #從colors表插入小虎,寫法:母表對象.子表名小寫_set.add(子表對象)。 讓喜歡藍色的child_set集合添加name="小虎"
#讓所有人都喜歡藍色
children_obj=models.Child.objects.all()
colors_obj=models.Colors.objects.get(colors="藍")
colors_obj.child_set.add(*children_obj)
#關于_set寫法,是否已經有些暈了,究竟什么時候使用_set,簡單記憶,只有子表才有"子表名小寫_set"的寫法,得到的是一個QuerySet集合,后邊可以接.add(),.remove(),.update(),.delete(),.clear()
#另外備注一下,colors_obj.child_set.clear()是讓所有人喜歡的顏色里去掉藍色,colors_obj.child_set.all().delete()是刪除.child_set的所有人

刪:

刪除多對多表關系 :

#刪除子表與母表關聯(lián)關系
#讓小虎不喜歡任何顏色
#寫法1:
child_obj=models.Child.objects.get(name="小虎")
colors_obj=models.Colors.objects.all()
child_obj.favor=''
child_obj.save()
#寫法2:
child_obj=models.Child.objects.get(name="小虎")
colors_obj=models.Colors.objects.all()
child_obj.favor.remove(*colors_obj)
#寫法3:
child_obj=models.Child.objects.get(name="小虎")
child_obj.favor.clear()
#其他例子參照多對多的增與改案例,這里不做舉例

#刪除母表與子表關聯(lián)關系
#讓所有人不再喜歡藍色
#寫法1:
children_obj=models.Child.objects.all()
colors_obj=models.Colors.objects.get(colors="藍")
colors_obj.child_set.remove(*children_obj)
#寫法2:
colors_obj=models.Colors.objects.get(colors="藍")
colors_obj.child_set.clear()

刪除多對多表數(shù)據(jù):

#刪除子表數(shù)據(jù)
#喜歡藍色的所有人都刪掉
colors_obj=models.Colors.objects.get(colors="藍")
colors_obj.child_set.all().delete() #注意有.all()
#刪除所有child
models.Child.objects.all().delete()

刪除母表數(shù)據(jù):

默認情況下,如此例中,刪除“紅”色,那么子表與顏色表是一對一或外鍵關系的,子表對應數(shù)據(jù)會自動刪除,如:紅球,小虎哥

與顏色表是多對多關系的話,不會自動刪除喜歡紅色的人,而是去掉紅色已選

如果想讓與母表外鍵關聯(lián)的子表在刪除外鍵之后依舊可以保留子表數(shù)據(jù),需要子表建表時加入以下字段:

class Clothes(models.Model):
 color=models.ForeignKey("Colors",null=True,on_delete=models.SET_NULL)) #可為空,如果外鍵被刪后,子表數(shù)據(jù)此字段置空而不是直接刪除這條數(shù)據(jù),同理也可以SET_DEFAULT,需要此字段有默認值
 description=models.CharField(max_length=10) #描述 

choice

#choices相當于實現(xiàn)一個簡化版的外鍵,外鍵的選項不能動態(tài)更新,如可選項目較少,可以采用
#先在models添加choices字段
class Child(models.Model):
 sex_choice=((0,"男"),(1,"女"))
 name=models.CharField(max_length=10) #姓名
 favor=models.ManyToManyField('Colors') #與顏色表為多對多
 sex=models.IntegerField(choices=sex_choice,default=0)
 def __unicode__(self):
  return self.name

#在views.py中調用
child_obj=models.Child.objects.get(name="小虎")
print(child_obj.sex) #返回0或1
print(child_obj.get_sex_display()) #返回男或女

以上這篇基于Django ORM、一對一、一對多、多對多的全面講解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Python內置函數(shù)詳細解析

    Python內置函數(shù)詳細解析

    這篇文章主要介紹了Python內置函數(shù)詳細解析,Python?自帶了很多的內置函數(shù),極大地方便了我們的開發(fā),下文小編總結了一些內置函數(shù)的相關內容,需要的小伙伴可以參考一下
    2022-05-05
  • Windows下的Jupyter Notebook 安裝與自定義啟動(圖文詳解)

    Windows下的Jupyter Notebook 安裝與自定義啟動(圖文詳解)

    這篇文章主要介紹了Windows下的Jupyter Notebook 安裝與自定義啟動(圖文詳解),需要的朋友可以參考下
    2018-02-02
  • Python中打印詳細堆棧信息的技巧分享

    Python中打印詳細堆棧信息的技巧分享

    在 Python 開發(fā)過程中,調試是一個不可或缺的環(huán)節(jié),當代碼出現(xiàn)問題時,能夠快速準確地定位問題所在是提高開發(fā)效率的關鍵,堆棧信息作為程序執(zhí)行過程中的調用記錄,對于理解程序的運行狀態(tài)和定位錯誤至關重要,需要的朋友可以參考下
    2024-11-11
  • Python項目文件中安裝?setup.py的步驟

    Python項目文件中安裝?setup.py的步驟

    大家都知道setup.py是python模塊分發(fā)與安裝的指導文件,這篇文章主要介紹了Python項目文件中如何安裝?setup.py,需要的朋友可以參考下
    2023-05-05
  • 對python字典元素的添加與修改方法詳解

    對python字典元素的添加與修改方法詳解

    今天小編就為大家分享一篇對python字典元素的添加與修改方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Python TCP全連接攻擊中SockStress全連接攻擊詳解

    Python TCP全連接攻擊中SockStress全連接攻擊詳解

    Sock Stress 全連接攻擊屬于TCP全連接攻擊,因為需要建立一次完整的TCP三次握手,該攻擊的關鍵點就在于,攻擊主機將windows窗口緩沖設置為0,實現(xiàn)的拒絕服務
    2022-10-10
  • python數(shù)據(jù)預處理 :數(shù)據(jù)共線性處理詳解

    python數(shù)據(jù)預處理 :數(shù)據(jù)共線性處理詳解

    今天小編就為大家分享一篇python數(shù)據(jù)預處理 :數(shù)據(jù)共線性處理詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • pytorch 6 batch_train 批訓練操作

    pytorch 6 batch_train 批訓練操作

    這篇文章主要介紹了pytorch 6 batch_train 批訓練操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • python中end=" "的含義及說明

    python中end=" "的含義及說明

    這篇文章主要介紹了python中end=" "的含義及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • python中super()函數(shù)的理解與基本使用

    python中super()函數(shù)的理解與基本使用

    super( )函數(shù)是用來調用父類的一個方法,super( )函數(shù)還用來解決多重繼承的問題,下面這篇文章主要給大家介紹了關于python中super()函數(shù)的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-08-08

最新評論

聂拉木县| 公安县| 左云县| 定陶县| 保定市| 大渡口区| 永新县| 鄂伦春自治旗| 夏津县| 延庆县| 昭通市| 香河县| 齐齐哈尔市| 枣庄市| 木里| 大渡口区| 伊宁县| 宁海县| 台安县| 霍山县| 潮州市| 罗定市| 公安县| 赣州市| 富锦市| 深泽县| 禄丰县| 尤溪县| 吕梁市| 普兰县| 平和县| 务川| 汝州市| 长海县| 丹凤县| 明溪县| 长白| 沙湾县| 余姚市| 美姑县| 刚察县|