Skip to content

djangodocs

Django 5.1
  • 6.1 current
  • 6.0
  • 5.2 LTS
  • 5.1 unsupported
  • 5.0 unsupported
  • 4.2 unsupported
  • 4.1 unsupported
  • 4.0 unsupported
  • 3.2 unsupported
  • 3.1 unsupported
  • 3.0 unsupported
  • 2.2 unsupported
  • 2.1 unsupported
  • 2.0 unsupported
简体中文
  • English
  • 简体中文
  • Français
  • 日本語
  • Bahasa Indonesia
  • Italiano
  • Português (Brasil)
  • 한국어
  • Español
  • Ελληνικά
  • Polski
Documentation contents
  • Django 文档
  • 开始
  • 使用 Django
  • 如何引导
  • Django FAQ
  • API 参考
    • 应用程序
    • 系统检查框架
    • 内置基于类的视图 API
    • 点击劫持保护
    • contrib 包
    • 跨站请求伪造保护
    • 数据库
    • django-admin 和 manage.py
    • Django 异常
    • 文件处理
    • 表单
    • 日志
    • 中间件
    • 迁移操作
    • 模型
      • 模型字段参考
      • 模型索引参考
      • 约束参考
      • 模型 _meta API
      • 关联对象参考
      • 模型类参考
      • 模型 Meta 选项
      • 模型实例参考
      • QuerySet API 参考
      • 查找 API 参考
      • 查询表达式
      • 条件表达式
      • 数据库函数
    • 分页器
    • 请求和响应对象
    • SchemaEditor
    • 配置
    • 信号
    • 模板
    • TemplateResponse 和 SimpleTemplateResponse
    • Unicode 数据
    • django.urls 实用函数
    • URLconfs 中使用的 django.urls 函数
    • Django 实用程序
    • 验证器
    • 内置视图
  • 元文件和杂记
  • 术语
  • 发行说明
  • Django内部
Django 5.1 is no longer supported. It receives no security fixes. Use it for reference only. Latest release
Chinese (Simplified) translation. Contributed by the Django community. 99.5% Help translate
  1. Django 5.1
  2. API 参考
  3. 模型

关联对象参考Link to this heading#

class RelatedManagerLink to this definition#

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

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

    Code
    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 关系的两端:

    Code
    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)Link to this definition#
aadd(*objs, bulk=True, through_defaults=None)Link to this definition#

异步版本: aadd

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

例如:

Python console
>>> 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 字典中的值,它们将在创建任何中间实例之前被执行一次。

create(through_defaults=None, **kwargs)Link to this definition#
acreate(through_defaults=None, **kwargs)Link to this definition#

异步版本: acreate

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

Python console
>>> 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.

这等同于(但比以下方式更简单):

Python console
>>> 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 参数为新的 中间模型 实例指定值。你可以使用可调用对象作为 through_defaults 字典中的值。

remove(*objs, bulk=True)Link to this definition#
aremove(*objs, bulk=True)Link to this definition#

异步版本: aremove

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

Python console
>>> 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)Link to this definition#
aclear(bulk=True)Link to this definition#

异步版本: aclear

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

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

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

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

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

set(objs, bulk=True, clear=False, through_defaults=None)Link to this definition#
aset(objs, bulk=True, clear=False, through_defaults=None)Link to this definition#

异步版本: aset

替换相关对象的集合:

Python console
>>> 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 字典中的值,它们将在创建任何中间实例之前被执行一次。

Note

请注意,add(), aadd(), create(), acreate(), remove(), aremove(), clear(), aclear(), set(), 和 aset() 对于所有类型的相关字段都会立即应用数据库更改。换句话说,在关系的两端都不需要调用 save()/asave()。

如果你使用 prefetch_related(),那么 add(), aadd(), remove(), aremove(), clear(), aclear(), set(), 和 aset() 方法会清除预取的缓存。

View as Markdown Edit this page on GitHub Official version
Previous模型 _meta API Next模型类参考

An unofficial rendering of the Django documentation.

Not affiliated with or endorsed by the Django Software Foundation. The documentation is copyright © Django Software Foundation and individual contributors, and is used under the BSD 3-Clause licence. “Django” is a trademark of the Django Software Foundation.

This translation is the work of the Django i18n community, not of this site. Read the official documentation at docs.djangoproject.com.

👋 Jason Cartwright