关联对象参考

class RelatedManager

“关系管理器”是一个用于处理一对多和多对多关系的管理器。在以下两种情况用到:

  • ForeignKey 关系的“另一边”。即:

    ``` from django.db import models

  1. class Blog(models.Model):
  2. # ...
  3. pass
  4. class Entry(models.Model):
  5. blog = models.ForeignKey(Blog, on_delete=models.CASCADE, null=True)
  6. ```
  7. In the above example, the methods below will be available on the manager `blog.entry_set`.
  • Both sides of a ManyToManyField relation

    ``` class Topping(models.Model):

    1. # ...
    2. pass
  1. class Pizza(models.Model):
  2. toppings = models.ManyToManyField(Topping)
  3. ```
  4. 在这个例子中,下文列出的方法在 `topping.pizza_set` 和 `pizza.toppings` 中均可用。
  • add(*objs, bulk=True, through_defaults=None)

  • aadd(*objs, bulk=True, through_defaults=None)

    Asynchronous version: aadd

    将指定的模型对象加入关联对象集。

    Example:

    1. >>> b = Blog.objects.get(id=1)
    2. >>> e = Entry.objects.get(id=234)
    3. >>> 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_addpost_add 动作。

    在已经存在的关系上使用 add() 不会重复关系,但仍然会触发信号。

    对于多对多关系,add() 接受模型实例或字段值,通常是主键,作为 *objs 参数。

    如果需要的话,使用 through_defaults 参数为新的 中间模型 实例指定值。你可以使用可调用对象作为 through_defaults 字典中的值,它们将在创建任何中间实例之前被执行一次。

    Changed in Django 4.2:

    aadd() method was added.

  • create(through_defaults=None, **kwargs)

  • acreate(through_defaults=None, **kwargs)

    Asynchronous version: acreate

    Creates a new object, saves it and puts it in the related object set. Returns the newly created object:

    1. >>> b = Blog.objects.get(id=1)
    2. >>> e = b.entry_set.create(
    3. ... headline="Hello", body_text="Hi", pub_date=datetime.date(2005, 1, 1)
    4. ... )
    5. # No need to call e.save() at this point -- it's already been saved.

    This is equivalent to (but simpler than):

    1. >>> b = Blog.objects.get(id=1)
    2. >>> e = Entry(blog=b, headline="Hello", body_text="Hi", pub_date=datetime.date(2005, 1, 1))
    3. >>> e.save(force_insert=True)

    无需指定定义了模型间关系的关键字参数。在上述例子中,我们并未向 create() 传递参数 blog。Django 知道要将新 Entry 对象的 blog 字段设置为 b

    如果需要的话,使用 through_defaults 参数为新的 中间模型 实例指定值。你可以使用可调用对象作为 through_defaults 字典中的值。

  • remove(*objs, bulk=True)

  • aremove(*objs, bulk=True)

    Asynchronous version: aremove

    Removes the specified model objects from the related object set:

    1. >>> b = Blog.objects.get(id=1)
    2. >>> e = Entry.objects.get(id=234)
    3. >>> 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 时,这个方法才存在。如果相关字段不能设置为 NoneNULL),那么一个对象就不能从一个关系中删除而不被添加到另一个关系中。在上面的例子中,从 b.entry_set() 中删除 e 相当于做了 e.blog = None,由于 blog ForeignKey` 没有 null=True,所以这是无效的。

    对于 ForeignKey 对象,这个方法接受一个 bulk 参数来控制如何执行操作。如果 True (默认),则使用 QuerySet.update()。如果 bulk=False,则调用每个单独模型实例的 save() 方法。这将触发 pre_savepost_save 信号,并以牺牲性能为代价。

    对于多对多关系,bulk 关键字参数不存在。

    Changed in Django 4.2:

    aremove() method was added.

  • clear(bulk=True)

  • aclear(bulk=True)

    Asynchronous version: aclear

    Removes all objects from the related object set:

    1. >>> b = Blog.objects.get(id=1)
    2. >>> b.entry_set.clear()

    请注意,这并不会删除相关的对象——只是将它们脱离关联。

    remove() 一样,clear() 只在 ForeignKey 上可用,其中 null=True,而且它还接受 bulk 关键字参数。

    对于多对多关系,bulk 关键字参数不存在。

    Changed in Django 4.2:

    aclear() method was added.

  • set(objs, bulk=True, clear=False, through_defaults=None)

  • aset(objs, bulk=True, clear=False, through_defaults=None)

    Asynchronous version: aset

    Replace the set of related objects:

    1. >>> new_list = [obj1, obj2, obj3]
    2. >>> 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 字典中的值,它们将在创建任何中间实例之前被执行一次。

    Changed in Django 4.2:

    aset() method was added.

备注

Note that add(), aadd(), create(), acreate(), remove(), aremove(), clear(), aclear(), set(), and aset() all apply database changes immediately for all types of related fields. In other words, there is no need to call save()/asave() on either end of the relationship.

If you use prefetch_related(), the add(), aadd(), remove(), aremove(), clear(), aclear(), set(), and aset() methods clear the prefetched cache.