“相关管理器”是在一对多或多对多相关上下文中使用的管理器。这发生在两种情况下:
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
上使用。
异步版本:aadd
将指定的模型对象添加到相关对象集中。
示例
>>> 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
字典中使用可调用对象作为值,它们将在创建任何中间实例之前被评估一次。
异步版本:acreate
创建一个新对象,保存它并将其放入相关对象集中。返回新创建的对象。
>>> 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
字典中使用可调用对象作为值。
异步版本:aremove
从相关对象集中删除指定的模型对象。
>>> 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
关键字参数不存在。
异步版本: aclear
移除关联对象集合中的所有对象
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()
注意,这不会删除关联的对象——它只是取消了它们的关联。
就像remove()
一样,clear()
只在ForeignKey
中null=True
时可用,并且它也接受bulk
关键字参数。
对于多对多关系,bulk
关键字参数不存在。
异步版本: aset
替换关联对象的集合
>>> 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
字典中使用可调用对象作为值,它们将在创建任何中间实例之前被评估一次。
注意
注意add()
,aadd()
,create()
,acreate()
,remove()
,aremove()
,clear()
,aclear()
,set()
和aset()
都对所有类型的关联字段立即应用数据库更改。换句话说,不需要在关系的两端调用save()
/asave()
。
如果使用prefetch_related()
,则add()
,aadd()
,remove()
,aremove()
,clear()
,aclear()
,set()
和aset()
方法将清除预取缓存。
_meta
API离线版 (Django 5.1): HTML | PDF | ePub
由 Read the Docs 提供。
© 2005-2024 Django 软件基金会 和个人贡献者。Django 是 Django 软件基金会的注册商标。