Django學(xué)習(xí)筆記:Models03 關(guān)系類型字段

多對一(ForeignKey)

多對一關(guān)系由外鍵實(shí)現(xiàn),外鍵要定義在“多”的一方而账,如:

models.ForeignKey(<主表>, ...)


如果要關(guān)聯(lián)的主表在另一個app中启摄,要顯式的指出:

models.ForeignKey(’<app名稱>.<主表>‘, ...)

?

可創(chuàng)建自己關(guān)聯(lián)自己的外鍵——比如凌外,在評論系統(tǒng)中伴栓,一條評論可被多次引用自身并繼續(xù)評論:

class Comment(models.Model):

????title = models.Charfield(max_length=128)

????text = models.TextField()

????parent_comment = models.ForeignKey(’self’, on_delete=models.CASCADE)

????...


如果在子模型中存在多個外鍵指向同一個主模型,必須給他們加上不同的related_name拳昌,用于反向查詢袭异。

外鍵字段在數(shù)據(jù)庫中的列名是<外鍵名>_id,用來儲存主表對象的id炬藤,因此御铃,在得到主表id的情況下可以不調(diào)用外鍵而直接篩選:

QuerySet = <外鍵表>.filter(<外鍵名>_id=<主表id>)

#獲得與“<主表id>=xxx的主對象”相關(guān)聯(lián)的子對象


多對一的字段參數(shù)

on_delete=models.XXX

當(dāng)主對象被刪除時,關(guān)聯(lián)的子對象的操作(因?yàn)橹麈I不能隨意刪除沈矿,外鍵可以直接刪除)

models.CASCADE:同時刪除關(guān)聯(lián)的子對象上真,Django默認(rèn)

models.PROTECT:阻止CASCADE刪除關(guān)聯(lián)的子對象,并彈出ProtectedError異常

models.SET_NULL:將子對象的外鍵字段設(shè)為null(外鍵字段需設(shè)置null=True)

models.SET_DEFAULT:將子對象的外鍵字段設(shè)為默認(rèn)值(外鍵字段需設(shè)置default=’xxx’)

models.DO_NOTHING:什么也不做

models.SET():設(shè)置為一個傳遞給SET()的值或一個回調(diào)函數(shù)的返回值

注:on_delete是Django2.0之后新增的必選項(xiàng)羹膳。


related_name=?

通過主對象反向引用子對象的通道名稱睡互,默認(rèn)名稱是<小寫子模型名>_set。

如:

class Car(models.Model):

????factory?= models.ForeignKey(

????????Factory, ?????

????????on_delete=models.CASCADE,

????????related_name='car_by_factory',

????)

此時Factory主表取出所有關(guān)聯(lián)的Car對象:factory.car_by_factory.all()

如果不想給外鍵設(shè)置反向關(guān)聯(lián)名稱陵像,就用related_name=’+’或以+號結(jié)尾


related_query_name=?

主對象反向關(guān)聯(lián)查詢的名稱就珠,默認(rèn)查詢名稱是<外鍵列>__<主表的某列>。

如:

class Tag(models.Model):

????article = models.ForeignKey(

????????Article,

????????on_delete=models.CASCADE,

????????related_query_name="tag",

????)

????name = models.CharField(max_length=255)

此時用tag作為查詢名稱:Article.objects.filter(tag__name="A")


limit_choices_to={}

限制外鍵能關(guān)聯(lián)的對象醒颖,用于Django的表單模塊和admin后臺妻怎,可以傳入字典、Q對象泞歉、一個返回字典或Q對象的函數(shù)逼侦。

如:

staff_member = models.ForeignKey(

????User,

????on_delete=models.CASCADE,

????limit_choices_to={'is_staff': True},

)

此時,表單模塊的staff_member字段列表中只會出現(xiàn)is_staff=True的Users對象腰耙,對admin后臺非常有用榛丢。


to_field=?

讓外鍵關(guān)聯(lián)到指定的字段上(默認(rèn)關(guān)聯(lián)到主鍵),該字段必須有unique=True屬性挺庞。


多對一的引用

子對象引用主對象:

<子對象>.<外鍵列>


主對象引用子對象:

<主對象>.<子表小寫>_set

如:

<主對象>.<子表小寫>_set.all() ?????????????????????????#所有關(guān)聯(lián)子對象的集合

<主對象>.<子表小寫>_set.create(<子表字段>=’xxx’, ...) ????#創(chuàng)建關(guān)聯(lián)的子對象

<主對象>.<子表小寫>_set.count() ??????????????????????#查詢關(guān)聯(lián)子對象的數(shù)量


添加多對一關(guān)系:

<子對象>.<外鍵列> = <主對象>

<子對象>.save()


刪除多對一關(guān)系:

<子對象>.<外鍵列> = None ????#外鍵列要設(shè)為null=True


多對一的查詢

查詢子對象的集合:

<子表>.objects.filter(<外鍵列>__<主表的某列>=’xxx’)

#獲得與“<主表的某列>=xxx的主對象”相關(guān)聯(lián)的子對象


查詢主對象的集合:

<主表>.objects.filter(<子表小寫> __<子表的某列>=’xxx’)

#獲得與“<子表的某列>=xxx的子對象”相關(guān)聯(lián)的主對象



多對多(ManyToManyField)

多對多字段可定義在任意一方晰赞,如:

models.ManyToManyField(‘<主表>’)

多對多字段不支持Django內(nèi)置的validators驗(yàn)證功能。

null參數(shù)對ManyToManyField多對多字段無效,設(shè)置null=True毫無意義宾肺。

如果在子模型中存在多個多對多鍵指向同一個主模型溯饵,必須給他們加上不同的related_name侵俗,用于反向查詢锨用。


采用默認(rèn)中間表的數(shù)據(jù)庫結(jié)構(gòu):

<中間表id> ?<多對多表>_id???<主表>_id

默認(rèn)中間表通過保存兩張表的id進(jìn)行關(guān)聯(lián)


采用自定義中間表并添加新字段的數(shù)據(jù)庫結(jié)構(gòu):

<中間表id> ?<新字段1> ?<新字段2> ?<多對多表>_id???<主表>_id


多對多字段的參數(shù)

related_name=?

主對象反向引用多對象時的名稱,和多對一相同隘谣。


related_query_name=?

主對象反向關(guān)聯(lián)查詢的名稱增拥,和多對一相同。


through=?

自定義中間表寻歧,用于保存兩表關(guān)系的附加數(shù)據(jù)掌栅,中間表要有兩個外鍵字段分別指向關(guān)聯(lián)的兩個模型。


through_fields=(<字段1>, <字段2>)

當(dāng)中間表有多個外鍵指向一個表的時候码泛,用through_firlds指定中間表的兩個連接字段猾封,如:

class Person(models.Model):

????name = models.CharField(max_length=32)


class Group(models.Model):

????name = models.CharField(max_length=64)

????members = models.ManyToManyField(

????????Person,

????????through='Membership',

????????through_fields=('group',?'person'?), ????#指定兩個連接字段

????)


class Membership(models.Model):

? ??group?= models.ForeignKey(Group, on_delete=models.CASCADE)

? ??person?= models.ForeignKey(Person, on_delete=models.CASCADE)

????inviter = models.ForeignKey(???????????????????????#另一個指向Person表的外鍵

????????Person,

????????on_delete=models.CASCADE,

????????related_name="membership_invites",

????)

????invite_reason = models.CharField(max_length=128)


db_table=?

設(shè)置中間表的名稱,默認(rèn)為<多對多字段名>_<主表名>_<一串哈希碼>


limit_choices_to={ }

限制多對多鍵關(guān)聯(lián)的對象噪珊,和多對一相同晌缘,對于用through定義中間表的字段無效。

?

多對多的引用

多對象引用主對象:

<多對象>.<多鍵列>


主對象引用多對象:

<主對象>.<多表小寫>_set


添加多對多關(guān)系:(默認(rèn)中間表)

<多對象>.<多鍵列>.add(<主對象>) ????#可同時添加多個主對象


添加多對多關(guān)系:(自定義中間表)

a = <主對象>

b = <多對象>

membership = <中間表>(<主表外鍵列>=a, <多表外鍵列>=b, <字段1>=’xxx’, <字段2>=’xxx’, ...)

membership.save()

#先創(chuàng)建主表和多表的實(shí)例痢站,再創(chuàng)建中間表的連接關(guān)系

#自定義中間表不能用add()磷箕、create()、remove()和set()操作對象的關(guān)系


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

<多對象>.<多鍵列>.clear()


獲取中間表的附加數(shù)據(jù):

a = <主對象>

b = <多對象>

membership = <中間表>.objects.get(<主表外鍵列>=a, <多表外鍵列>=b)

membership.<字段1> ????#獲取字段信息



一對一(OneToOneField)

反向關(guān)聯(lián)的對象只有一個阵难,多數(shù)用于從一個模型擴(kuò)展出另一個模型的情況岳枷。

一對一通過子對象訪問關(guān)聯(lián)的主對象:

<子對象>.<一對一鍵>


一對一通過主對象訪問關(guān)聯(lián)的子對象:

<主對象>.<小寫子模型名>

注意返回的是單個對象而不是集合。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末呜叫,一起剝皮案震驚了整個濱河市空繁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌朱庆,老刑警劉巖家厌,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異椎工,居然都是意外死亡饭于,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門维蒙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掰吕,“玉大人,你說我怎么就攤上這事颅痊≈呈欤” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵斑响,是天一觀的道長菱属。 經(jīng)常有香客問我钳榨,道長,這世上最難降的妖魔是什么纽门? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任薛耻,我火速辦了婚禮,結(jié)果婚禮上赏陵,老公的妹妹穿的比我還像新娘饼齿。我一直安慰自己,他們只是感情好蝙搔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布缕溉。 她就那樣靜靜地躺著,像睡著了一般吃型。 火紅的嫁衣襯著肌膚如雪证鸥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天勤晚,我揣著相機(jī)與錄音枉层,去河邊找鬼。 笑死运翼,一個胖子當(dāng)著我的面吹牛返干,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播血淌,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼矩欠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悠夯?” 一聲冷哼從身側(cè)響起癌淮,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎沦补,沒想到半個月后乳蓄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡夕膀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年虚倒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片产舞。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡魂奥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出易猫,到底是詐尸還是另有隱情耻煤,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站哈蝇,受9級特大地震影響棺妓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炮赦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一怜跑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧眼五,春花似錦妆艘、人聲如沸彤灶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幌陕。三九已至诵姜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搏熄,已是汗流浹背棚唆。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留心例,地道東北人宵凌。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像止后,于是被迫代替她去往敵國和親瞎惫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容