基于Django中ORM、一對(duì)一、一對(duì)多、多對(duì)多的示例分析-創(chuàng)新互聯(lián)

這篇文章主要介紹了基于Django中ORM、一對(duì)一、一對(duì)多、多對(duì)多的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)建站從2013年開(kāi)始,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元興安盟做網(wǎng)站,已為上家服務(wù),為興安盟各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108

1.1首先我們先看一個(gè)小案例:

#_*_coding:utf-8_*_
from django.db import models
 
# Create your models here.
 
class Colors(models.Model):
 colors=models.CharField(max_length=10) #藍(lán)色
 def __str__(self):
  return self.colors
 
class Ball(models.Model):
 color=models.OneToOneField("Colors") #與顏色表為一對(duì)一,顏色表為母表
 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') #與顏色表為多對(duì)多

先來(lái)區(qū)分一下什么是一對(duì)一、多對(duì)多

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

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

共同點(diǎn)是在admin中添加數(shù)據(jù)的話,都會(huì)出現(xiàn)一個(gè)select選框,但只能單選,因?yàn)椴徽撘粚?duì)一還是一對(duì)多,自己都是“一”

多對(duì)多總結(jié):

比如有多個(gè)孩子,和多種顏色、

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

應(yīng)用場(chǎng)景

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

外鍵:有很多的應(yīng)用場(chǎng)景,比如每個(gè)員工歸屬于一個(gè)部門(mén),那么就可以讓員工表的部門(mén)字段與部門(mén)表進(jìn)行一對(duì)多關(guān)聯(lián),可以查詢到一個(gè)員工歸屬于哪個(gè)部門(mén),也可反向查出某一部門(mén)有哪些員工

多對(duì)多:如很多公司,一臺(tái)服務(wù)器可能會(huì)有多種用途,歸屬于多個(gè)產(chǎn)品線當(dāng)中,那么服務(wù)器與產(chǎn)品線之間就可以做成對(duì)多對(duì),多對(duì)多在A表添加manytomany字段或者從B表添加,效果一致

一對(duì)一

查:

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


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

增:

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

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

#增添數(shù)據(jù)的三種寫(xiě)法:
#寫(xiě)法1:
color_obj=models.Colors.objects.create(colors="黑")
models.Ball.objects.create(color=color_obj,description="黑球")
#寫(xiě)法1補(bǔ)充:
color_id=models.Colors.objects.create(colors="黑").id
models.Ball.objects.create(color_id=color_id,description="黑球")
#寫(xiě)法2:
color_obj=models.Colors.objects.create(colors="黑")
ball_obj=models.Ball(color=color_obj,description="黑球")
ball_obj.save()
#寫(xiě)法3(字典導(dǎo)入):
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ù)的常見(jiàn)方式

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

刪:

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

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

一對(duì)多(外鍵)

查:

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

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

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

備注:通過(guò)QuerySet的.values()方法,將QuerySet轉(zhuǎn)化為ValuesQuerySet

print(models.Clothes.objects.filter(color=models.Colors.objects.get(colors="紅")).values('color__colors','description')) #獲取子表的description字段,和母表的colors字段,獲取母表字段寫(xiě)法: 子表外鍵字段名__母表字段名--適用于values()或filter()
#簡(jiǎn)寫(xiě)形式補(bǔ)充:
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: 小虎哥>]這樣一個(gè)QuerySet集合,通過(guò)values可以形成一個(gè)列表,列表中的每一個(gè)元素是一個(gè)字典,可以通過(guò)list()將ValuesQeurySet轉(zhuǎn)化為列表,之后返回給templates


#另外可通過(guò).values_list()將QuerySet轉(zhuǎn)化為ValuesListQuerySet。返回:[(u'\u7ea2', u'\u7ea2\u889c\u5b50'), (u'\u7ea2', u'\u7ea2\u889c\u5b50')]
#得到的是一個(gè)列表,列表中是多個(gè)元組,每個(gè)元組是ValuesQuerySet中字典的value,常用于從models里將數(shù)據(jù)取出后動(dòng)態(tài)添加到前端模板中的select選項(xiàng)中。
#通過(guò)forms.py從models取值傳給前端select選項(xiàng),需重啟django后,select選項(xiàng)才能更新,可在定義form時(shí),添加如下關(guān)鍵字保障動(dòng)態(tài)更新select選項(xiàng)
#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): #定義這個(gè)關(guān)鍵字段,當(dāng)使用form時(shí),colors表新增了顏色,前端ClothesForm的color字段的選項(xiàng)會(huì)自動(dòng)更新
  super(ClothesForm, self).__init__(*args,**kwargs)
  self.fields['color'].widget.choices=models.Colors.objects.all().order_by('id').values_list('id','colors')

增:

#增添子表數(shù)據(jù),形式與一對(duì)一一致
#添加顏色為綠的服裝:小帥哥
#方法1:
models.Clothes.objects.create(color=models.Colors.objects.get(colors="綠"),description="小帥哥")
#方法1補(bǔ)充:
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:字典方式錄入..參考一對(duì)一

改:

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

刪:

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

多對(duì)多

查:

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


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

增與改(增添子表或母表數(shù)據(jù)參照一對(duì)一的增,多對(duì)多重點(diǎn)在于關(guān)系表的對(duì)應(yīng)關(guān)系變更):

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


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

刪:

刪除多對(duì)多表關(guān)系 :

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

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

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

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

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

默認(rèn)情況下,如此例中,刪除“紅”色,那么子表與顏色表是一對(duì)一或外鍵關(guān)系的,子表對(duì)應(yīng)數(shù)據(jù)會(huì)自動(dòng)刪除,如:紅球,小虎哥

與顏色表是多對(duì)多關(guān)系的話,不會(huì)自動(dòng)刪除喜歡紅色的人,而是去掉紅色已選

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

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

choice

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

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

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“基于Django中ORM、一對(duì)一、一對(duì)多、多對(duì)多的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司,關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、網(wǎng)站設(shè)計(jì)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

當(dāng)前名稱:基于Django中ORM、一對(duì)一、一對(duì)多、多對(duì)多的示例分析-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)URL:http://muchs.cn/article6/hejig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google定制網(wǎng)站、網(wǎng)站制作建站公司、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、定制開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)