https://docs.djangoproject.com/en/2.1/ref/models/relations/
关系管理器用于 一对多、 多对多关系中。包括:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date pulbished')
def was_published_recently(self):
return self.pub_date >= timezone.now()
def __str__(self):
return "Question:%s" % self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question,on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return "Choice:%s,%s" % (str(self.question), self.choice_text)
这样,就可以使用:Quesion.choice_set
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)
topping.pizza_set 和 pizza.toppings 都是正确的。
add(*objs, bulk=True)
用于将特定的model 对象加入到相关对象set 中。
例如:
In [16]: c=Choice(choice_text="test",votes=0)
In [18]: c.save()
In [19]: q.choice_set.add(c)
在调用add 方法时,会调用对应的c.save()方法来执行更新。如在调用add方法后,Choice对象会添加更新了question的信息,另外,Question对象上会多关联一个Choice对象。例如:
In [19]: q.choice_set.add(c)
In [20]: q.choice_set.all()
Out[20]: <QuerySet [<Choice: Choice:Question:what's new?,test>]>
In [21]: c.question
Out[21]: <Question: Question:what's new?>
注意:在调用add(object)之前,需要object 已经保存过(调用过save方法),否则会跑错,例如:
In [16]: c=Choice(choice_text="test",votes=0)
In [17]: q.choice_set.add(c)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-17-39833237dde1> in <module>()
----> 1 q.choice_set.add(c)
~/.pyenv/versions/3.6.0/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py in add(self, *objs, **kwargs)
591 raise ValueError(
592 "%r instance isn't saved. Use bulk=False or save "
--> 593 "the object first." % obj
594 )
595 pks.append(obj.pk)
ValueError: <Choice: Choice:Question:what's new?,test> instance isn't saved. Use bulk=False or save the object first.
或者如果你觉得自己调用save 比较麻烦的话,可以通过add(object,bulk=False)的方式,要求关联管理器来帮你调用c.save函数。例如:
In [37]: c=Choice(choice_text="test bulk",votes=1)
In [38]: q.choice_set.add(c,bulk=False)
In [39]: c.question
Out[39]: <Question: Question:what's new?>
注意:
在多对多关系中,调用add方法不会调用任何的save 函数(不支持bulk参数)。但是,你可以调用 QuerySet.bulk_create()。如果你需要在关系创建的时候,执行自定义的逻辑,可以监听m2m_changed信号,该信号会触发pre_add,post_add动作。
create(**kwargs)
方法作用:创建一个新对象,并将对象保存并放到relate object set 中,并返回新创建的对象。
In [40]: c=q.choice_set.create(choice_text="create method",votes=2)
In [42]: c.question
Out[42]: <Question: Question:what's new?>
上述代码等同于:
In [46]: q=Question.objects.get(pk=1)
In [44]: c=Choice(question=q,choice_text="normal create",votes=1)
In [45]: c.save(force_insert=True)
remove(*objs, bulk=True)
将相关对象从关联对象集中移除。和add()方法类似,会调用c.save()函数来执行更新操作。对于多对多关系中,调用remove 方法 会导致QuerySet.delete函数的调用(因此,则不会调用任何的save方法)。如果你想在执行关系删除的时候,执行自定义的代码,则可以监听m2m_changed信号。
在ForeiginKey这端,只有 ForeignKey 字段的null 属性为True 时,才能调用remove方法,即如下形式,允许question字段为空。因为调用remove 等价于choice.question=None。
class Choice(models.Model):
question = models.ForeignKey(Question,on_delete=models.CASCADE, null=True)
对于ForeignKey场景下,bulk属性的作用同add。默认情况下bulk =True,执行的更新操作(即需要对象之前调用过save 方法)
在多对多关系中,不支持bulk参数。
clear(bulk=True)
清除所有的关联关系。
注意:该方法不会删除对象,而只是清除了关系。同remove 方法,需要Foreginkey 端支持null =True,可以设置为空。
set(objs, bulk=True, clear=False)
重置关联关系。
该方法有一个clear 参数。如果clear=False ,则将不再objes 中的元素使用remove()方法移除。如果clear=True,则首先调用clear()方法将之前的元素全部删除掉,再将集合中的元素整个删除。
注意:
如果你使用了中间模型(保存多对多的关系),则add,create,remove,set方法都不能调用