---
title: "关联对象参考"
version: 6.1
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/6.1/ref/models/relations/
canonical: https://djangodocs.dev/zh-hans/6.1/ref/models/relations/
---
# 关联对象参考

#### `class RelatedManager`

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

- [`ForeignKey`](/zh-hans/6.1/ref/models/fields/#django.db.models.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`](/zh-hans/6.1/ref/models/fields/#django.db.models.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)`

#### `aadd(*objs, bulk=True, through_defaults=None)`

*异步版本*: `aadd`

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

例如：

```pycon
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e)  # Associates Entry e with Blog b.
```

上述例子中，由于有 [`ForeignKey`](/zh-hans/6.1/ref/models/fields/#django.db.models.ForeignKey) 关系，才可以使用 [`QuerySet.update()`](/zh-hans/6.1/ref/models/querysets/#django.db.models.query.QuerySet.update) 更新数据。这要求对象事先已经被保存在数据库内了。

你可以使用 `bulk=False` 参数让关系管理器通过调用 `e.save()` 来执行更新操作。

但是，在多对多关系中使用 `add()`，不会调用任何 `save()` 方法（`bulk` 参数不存在），而是使用 `QuerySet.bulk_create()` 创建关系。如果需要在创建关系时执行一些自定义逻辑，可以监听 [`m2m_changed`](/zh-hans/6.1/ref/signals/#django.db.models.signals.m2m_changed) 信号，它将触发 `pre_add` 和 `post_add` 动作。

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

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

如果需要的话，使用 `through_defaults` 参数为新的 [中间模型](/zh-hans/6.1/topics/db/models/#intermediary-manytomany) 实例指定值。你可以使用可调用对象作为 `through_defaults` 字典中的值，它们将在创建任何中间实例之前被执行一次。

#### `create(through_defaults=None, **kwargs)`

#### `acreate(through_defaults=None, **kwargs)`

*异步版本*: `acreate`

创建一个新对象，保存它并将它放入相关对象集中。返回新创建的对象：

```pycon
>>> 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.
```

这等同于（但比以下方式更简单）：

```pycon
>>> 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)
```

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

如果需要的话，使用 `through_defaults` 参数为新的 [中间模型](/zh-hans/6.1/topics/db/models/#intermediary-manytomany) 实例指定值。你可以使用可调用对象作为 `through_defaults` 字典中的值。

#### `remove(*objs, bulk=True)`

#### `aremove(*objs, bulk=True)`

*异步版本*: `aremove`

从相关对象集中删除指定的模型对象：

```pycon
>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e)  # Disassociates Entry e from Blog b.
```

Similar to [`add()`](#django.db.models.fields.related.RelatedManager.add), `e.save()` is called in the example above
to perform the update. Using `remove()` with a many-to-many
relationship, however, will delete the relationships using
[`QuerySet.delete()`](/zh-hans/6.1/ref/models/querysets/#django.db.models.query.QuerySet.delete) which
means no model `save()` methods are called; listen to the
[`m2m_changed`](/zh-hans/6.1/ref/signals/#django.db.models.signals.m2m_changed) signal if you wish to
execute custom code when a relationship is deleted.

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

对于 [`ForeignKey`](/zh-hans/6.1/ref/models/fields/#django.db.models.ForeignKey) 对象，只有当 `null=True` 时，这个方法才存在。如果相关字段不能设置为 `None` （`NULL`），那么一个对象就不能从一个关系中删除而不被添加到另一个关系中。在上面的例子中，从 `b.entry_set()` 中删除 `e` 相当于做了 `e.blog = None`，由于 `blog` `` ForeignKey` `` 没有 `null=True`，所以这是无效的。

对于 [`ForeignKey`](/zh-hans/6.1/ref/models/fields/#django.db.models.ForeignKey) 对象，这个方法接受一个 `bulk` 参数来控制如何执行操作。如果 `True` （默认），则使用 `QuerySet.update()`。如果 `bulk=False`，则调用每个单独模型实例的 `save()` 方法。这将触发 [`pre_save`](/zh-hans/6.1/ref/signals/#django.db.models.signals.pre_save) 和 [`post_save`](/zh-hans/6.1/ref/signals/#django.db.models.signals.post_save) 信号，并以牺牲性能为代价。

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

#### `clear(bulk=True)`

#### `aclear(bulk=True)`

*异步版本*: `aclear`

从相关对象集中删除所有对象：

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

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

和 `remove()` 一样，`clear()` 只在 [`ForeignKey`](/zh-hans/6.1/ref/models/fields/#django.db.models.ForeignKey) 上可用，其中 `null=True`，而且它还接受 `bulk` 关键字参数。

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

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

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

*异步版本*: `aset`

替换相关对象的集合：

```pycon
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)
```

本方法接受一个 `clear` 参数来控制如何执行操作。如果 `False` （默认），则使用 `remove()` 删除新集合中缺少的元素，只添加新元素。如果 `clear=True`，则调用 `clear()` 方法，一次性添加整个集合。

对于 [`ForeignKey`](/zh-hans/6.1/ref/models/fields/#django.db.models.ForeignKey) 对象，`bulk` 参数被传递给 [`add()`](#django.db.models.fields.related.RelatedManager.add) 和 [`remove()`](#django.db.models.fields.related.RelatedManager.remove)。

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

请注意，由于 `set()` 是一个复合操作，它受到竞争条件的影响。例如，在调用 `clear()` 和调用 `add()` 之间可能会向数据库中添加新的对象。

对于多对多关系，`set()` 接受一个模型实例或字段值的列表，通常是主键，作为 `objs` 参数。

如果需要的话，使用 `through_defaults` 参数为新的 [中间模型](/zh-hans/6.1/topics/db/models/#intermediary-manytomany) 实例指定值。你可以使用可调用对象作为 `through_defaults` 字典中的值，它们将在创建任何中间实例之前被执行一次。

> **Note**
>
> 请注意，`add()`, `aadd()`, `create()`, `acreate()`, `remove()`, `aremove()`, `clear()`, `aclear()`, `set()`, 和 `aset()` 对于所有类型的相关字段都会立即应用数据库更改。换句话说，在关系的两端都不需要调用 `save()`/`asave()`。
>
> 如果你使用 [`prefetch_related()`](/zh-hans/6.1/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related)，那么 `add()`, `aadd()`, `remove()`, `aremove()`, `clear()`, `aclear()`, `set()`, 和 `aset()` 方法会清除预取的缓存。
