# Django 2.2.9.dev20191202104323 文档

# 关系对象参考

class `RelatedManager`

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

  - “另一边”的关联关系 `ForeignKey`。即:

        from django.db import models

        class Reporter(models.Model):
            # ...
            pass

        class Article(models.Model):
            reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

    在上面的例子中，以下方法会在管理器 `reporter.article_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()` 来执行更新操作。

    Using `add()` with a many-to-many relationship, however, will not call any `save()` methods (the `bulk` argument doesn't exist), but rather create the relationships using `QuerySet.bulk_create()`. If you need to execute some custom logic when a relationship is created, listen to the `m2m_changed` signal, which will trigger `pre_add` and `post_add` actions.

    Using `add()` on a relation that already exists won't duplicate the relation, but it will still trigger signals.

    `add()` also accepts the field the relation points to as an argument. The above example can be rewritten as `b.entry_set.add(234)`.

    Use the `through_defaults` argument to specify values for the new intermediate model instance(s), if needed.

    Changed in Django 2.2:

    The `through_defaults` argument was added.

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

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

    Use the `through_defaults` argument to specify values for the new intermediate model instance, if needed.

    Changed in Django 2.2:

    The `through_defaults` argument was added.

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

    Similar to `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()` which means no model `save()` methods are called; listen to the `m2m_changed` signal if you wish to execute custom code when a relationship is deleted.

    Similarly to `add()`, `remove()` also accepts the field the relation points to as an argument. The above example can be rewritten as `b.entry_set.remove(234)`.

    For `ForeignKey` objects, this method only exists if `null=True`. If the related field can't be set to `None` (`NULL`), then an object can't be removed from a relation without being added to another. In the above example, removing `e` from `b.entry_set()` is equivalent to doing `e.blog = None`, and because the `blog` `ForeignKey` doesn't have `null=True`, this is invalid.

    For `ForeignKey` objects, this method accepts a `bulk` argument to control how to perform the operation. If `True` (the default), `QuerySet.update()` is used. If `bulk=False`, the `save()` method of each individual model instance is called instead. This triggers the `pre_save` and `post_save` signals and comes at the expense of performance.

    For many-to-many relationships, the `bulk` keyword argument doesn't exist.

  `clear`(bulk=True)

    清空关系集合:

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

    Note this doesn't delete the related objects -- it just disassociates them.

    Just like `remove()`, `clear()` is only available on `ForeignKey`s where `null=True` and it also accepts the `bulk` keyword argument.

    For many-to-many relationships, the `bulk` keyword argument doesn't exist.

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

    Replace the set of related objects:

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

    This method accepts a `clear` argument to control how to perform the operation. If `False` (the default), the elements missing from the new set are removed using `remove()` and only the new ones are added. If `clear=True`, the `clear()` method is called instead and the whole set is added at once.

    For `ForeignKey` objects, the `bulk` argument is passed on to `add()` and `remove()`.

    For many-to-many relationships, the `bulk` keyword argument doesn't exist.

    Note that since `set()` is a compound operation, it is subject to race conditions. For instance, new objects may be added to the database in between the call to `clear()` and the call to `add()`.

    Similarly to `add()`, `set()` also accepts the field the relation points to as an argument. The above example can be rewritten as `e.related_set.set([obj1.pk, obj2.pk, obj3.pk])`.

    Use the `through_defaults` argument to specify values for the new intermediate model instance(s), if needed.

    Changed in Django 2.2:

    The `through_defaults` argument was added.

  注解

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

  If you use `prefetch_related()`, the `add()`, `remove()`, `clear()`, and `set()` methods clear the prefetched cache.