相关对象参考
- class RelatedManager
“相关管理器”是在一对多或多对多相关上下文中使用的管理器。 这发生在两种情况下:
ForeignKey 关系的“另一面”。 那是:
from django.db import models class Blog(models.Model): # ... pass class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)
在上面的例子中,下面的方法将在管理器
blog.entry_set
上可用。ManyToManyField 关系的两边:
class Topping(models.Model): # ... pass class Pizza(models.Model): toppings = models.ManyToManyField(Topping)
在此示例中,以下方法在
topping.pizza_set
和pizza.toppings
上均可用。
- add(*objs, bulk=True, through_defaults=None)
将指定的模型对象添加到相关对象集。
例子:
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.add(e) # Associates Entry e with Blog b.
在上面的例子中,在 ForeignKey 关系的情况下,QuerySet.update() 用于执行更新。 这需要已保存对象。
您可以使用
bulk=False
参数来让相关管理器通过调用e.save()
来执行更新。然而,使用具有多对多关系的
add()
不会调用任何save()
方法(bulk
参数不存在),而是使用创建关系QuerySet.bulk_create()。 如果您需要在创建关系时执行一些自定义逻辑,请收听 m2m_changed 信号,这将触发pre_add
和post_add
动作。在已存在的关系上使用
add()
不会复制该关系,但仍会触发信号。对于多对多关系,
add()
接受模型实例或字段值,通常是主键,作为*objs
参数。如果需要,使用
through_defaults
参数为新的 中间模型 实例指定值。 您可以将可调用对象用作through_defaults
字典中的值,它们将在创建任何中间实例之前评估一次。3.1 版更改:
through_defaults
值现在可以是可调用的。
- create(through_defaults=None, **kwargs)
创建一个新对象,保存它并将其放入相关对象集中。 返回新创建的对象:
>>> b = Blog.objects.get(id=1) >>> e = b.entry_set.create( ... headline='Hello', ... body_text='Hi', ... pub_date=datetime.date(2005, 1, 1) ... ) # No need to call e.save() at this point -- it's already been saved.
这相当于(但比):
>>> b = Blog.objects.get(id=1) >>> e = Entry( ... blog=b, ... headline='Hello', ... body_text='Hi', ... pub_date=datetime.date(2005, 1, 1) ... ) >>> e.save(force_insert=True)
请注意,无需指定定义关系的模型的关键字参数。 在上面的例子中,我们没有将参数
blog
传递给create()
。 Django 发现新的Entry
对象的blog
字段应该设置为b
。如果需要,使用
through_defaults
参数为新的 中间模型 实例指定值。 您可以将可调用对象用作through_defaults
字典中的值。3.1 版更改:
through_defaults
值现在可以是可调用的。
- remove(*objs, bulk=True)
从相关对象集中移除指定的模型对象:
>>> b = Blog.objects.get(id=1) >>> e = Entry.objects.get(id=234) >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
与 add() 类似,在上面的示例中调用
e.save()
来执行更新。 然而,使用具有多对多关系的remove()
将删除使用 QuerySet.delete() 的关系,这意味着没有调用模型save()
方法; 如果您希望在删除关系时执行自定义代码,请收听 m2m_changed 信号。对于多对多关系,
remove()
接受模型实例或字段值,通常是主键,作为*objs
参数。对于 ForeignKey 对象,此方法仅在
null=True
时存在。 如果无法将相关字段设置为None
(NULL
),则无法从关系中删除对象而不将其添加到另一个。 在上面的例子中,从b.entry_set()
中删除e
相当于做e.blog = None
,因为blog
ForeignKey 没有null=True
,无效。对于 ForeignKey 对象,此方法接受
bulk
参数来控制如何执行操作。 如果True
(默认),则使用QuerySet.update()
。 如果是bulk=False
,则改为调用每个单独模型实例的save()
方法。 这会触发 pre_save 和 post_save 信号,并以牺牲性能为代价。对于多对多关系,
bulk
关键字参数不存在。
- clear(bulk=True)
从相关对象集中删除所有对象:
>>> b = Blog.objects.get(id=1) >>> b.entry_set.clear()
请注意,这不会删除相关对象——它只是解除了它们的关联。
就像
remove()
,clear()
仅在 ForeignKeys 上可用,其中null=True
并且它也接受bulk
关键字参数。对于多对多关系,
bulk
关键字参数不存在。
- set(objs, bulk=True, clear=False, through_defaults=None)
替换相关对象集:
>>> new_list = [obj1, obj2, obj3] >>> e.related_set.set(new_list)
此方法接受
clear
参数来控制如何执行操作。 如果是False
(默认值),则使用remove()
删除新集合中缺少的元素,并且仅添加新元素。 如果是clear=True
,则改为调用clear()
方法并立即添加整个集合。对于 ForeignKey 对象,
bulk
参数传递给 add() 和 remove()。对于多对多关系,
bulk
关键字参数不存在。请注意,由于
set()
是复合操作,因此会受到竞争条件的影响。 例如,可以在调用clear()
和调用add()
之间将新对象添加到数据库中。对于多对多关系
set()
接受模型实例或字段值的列表,通常是主键,作为objs
参数。如果需要,使用
through_defaults
参数为新的 中间模型 实例指定值。 您可以将可调用对象用作through_defaults
字典中的值,它们将在创建任何中间实例之前评估一次。3.1 版更改:
through_defaults
值现在可以是可调用的。
笔记
请注意,
add()
、create()
、remove()
、clear()
和set()
都立即对所有类型的相关字段应用数据库更改。 换句话说,不需要在关系的任何一端调用save()
。如果使用 prefetch_related(),则
add()
、remove()
、clear()
和set()
方法清除预取缓存。