一對多
外鍵字段是放在多的一方模型類里面的
比如,一輛汽車(Car)有一個(gè)制造商(Manufacturer) —— 但是一個(gè)制造商(Manufacturer) 生產(chǎn)很多汽車(Car),每一輛汽車(Car) 只能有一個(gè)制造商(Manufacturer) —— 使用下面的定義:
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
company_that_makes_it = models.ForeignKey(Manufacturer)
如果想要?jiǎng)?chuàng)建和自己關(guān)聯(lián)的一對多關(guān)系,使用self指向自己
models.ForeignKey('self')
一對多的使用和綁定
準(zhǔn)備數(shù)據(jù)
比如有下面兩個(gè)模型類
from django.db import models
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
def __str__(self): # __unicode__ on Python 2
return "%s %s" % (self.first_name, self.last_name)
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter)
def __str__(self): # __unicode__ on Python 2
return self.headline
class Meta:
ordering = ('headline',)
關(guān)聯(lián)對象
默認(rèn)方式
# 創(chuàng)建幾個(gè)Reporter:
>>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r.save()
>>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
>>> r2.save()
#創(chuàng)建一個(gè)Article:
>>> from datetime import date
>>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r)
>>> a.save()
>>> a.reporter.id
1
>>> a.reporter
<Reporter: John Smith>
# 注意,將對象分配給一個(gè)外鍵之前必須保存。例如,使用未保存的Reporter 創(chuàng)建Article 將引發(fā)ValueError:
>>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> Article(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3)
Traceback (most recent call last):
...
ValueError: 'Cannot assign "<Reporter: John Smith>": "Reporter" instance isn't saved in the database.'
#訪問關(guān)聯(lián)對象,具體看模型的查詢
>>> r = a.reporter
>>> r.first_name, r.last_name
('John', 'Smith')
除了上面的方式外還有幾個(gè)內(nèi)建的關(guān)聯(lián)對象的方法,add,create,remove,clear
add(obj1, obj2, ...)添加一指定的模型對象到關(guān)聯(lián)的對象集中。
>>> r1 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r1.save()
>>> a1 = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27))
>>> a1.save()
>>> r1.article_set.add(a1)create(**kwargs)創(chuàng)建一個(gè)新的對象,將它保存并放在關(guān)聯(lián)的對象集中。返回新創(chuàng)建的對象。
>>> r1 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r1.save()
>>> r1.article_set.create(headline="This is a test", pub_date=date(2005, 7, 27))remove(obj1, obj2, ...)從關(guān)聯(lián)的對象集中刪除指定的模型對象。
>>> r1 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r1.save()
>>> r1.article_set.create(headline="This is a test", pub_date=date(2005, 7, 27))
>>> a1 = Article.objects.filter(id=1)
>>> r1.article_set.remove(a1)clear()從關(guān)聯(lián)的對象集中刪除所有的對象。
>>> r1 = Reporter(first_name='John', last_name='Smith', email='john@example.com')
>>> r1.save()
>>> r1.article_set.create(headline="This is a test", pub_date=date(2005, 7, 27))
>>> r1.article_set.clear()一次性關(guān)聯(lián)多個(gè)對象
若要一次性給關(guān)聯(lián)的對象集賦值,只需要給它賦值一個(gè)可迭代的對象。這個(gè)可迭代的對象可以包含對象的實(shí)例,或者一個(gè)主鍵值的列表。
>>> r1 = Reporter.objects.get(id=1)
>>> r1.entry_set = [a1, a2]
a1 和a2 可以是Article 實(shí)例,也可以是Article實(shí)例主鍵的整數(shù)值。
外鍵關(guān)聯(lián)對象的查找(或者說是索引也可以說是獲取)或者說是關(guān)聯(lián)模型的反向查詢
比如有兩個(gè)模型類A和B,A是多的一方,B是一的一方,外鍵字段是設(shè)置在多的一方里面的
-
使用默認(rèn)方式(源模型名__set方式) 源模型名要小寫
class A(models.Model):
age = models.IntField()
obj_b = models.ForeignKey(B)class B(modes.Model):
name = models.CharField()
passb1 = B()
b1.save()
a1 = A(b=b1)
a1.save()
那么a拿到b的對象
a1.obj_b.name 就能拿到了 a對象綁定的b對象的name字段值
那么b怎么拿到a 呢 使用源模型名(小寫)__set方法
b1.a_set.age b就拿到了關(guān)聯(lián)的a對象的age字段值 -
使用related_name屬性(覆蓋上面的默認(rèn)方式)
class A(models.Model):
age = models.IntField()
obj_b = models.ForeignKey(B,related_name="obj_a")class B(modes.Model):
name = models.CharField()
passb1 = B()
b1.save()
a1 = A(b=b1)
a1.save()
a拿到b的方式還是一樣的
a1.obj_b.name 就能拿到了 a對象綁定的b對象的name字段值
b拿到a 的方式變了,不在是源模型名__set,而是related_name指定的值
b1.obj_a.age b1就拿到了關(guān)聯(lián)的a1對象的age字段值