---
title: "信号"
version: 4.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/4.2/ref/signals/
canonical: https://djangodocs.dev/zh-hans/4.2/ref/signals/
---
# 信号

Django 发送的所有信号的列表。所有内置的信号都是使用 [`send()`](/zh-hans/4.2/topics/signals/#django.dispatch.Signal.send) 方法发送的。

> **See also**
>
> 关于如何注册和接收信号的信息，请参见 [信号收发](/zh-hans/4.2/topics/signals/) 的文档。
>
> [认证框架](/zh-hans/4.2/topics/auth/) 在 [用户登录／退出时发送信号](/zh-hans/4.2/ref/contrib/auth/#topics-auth-signals)。

## 模型信号

[`django.db.models.signals`](#module-django.db.models.signals) 模块定义了一组由模型系统发送的信号。

> **Warning**
>
> 信号可以使您的代码更难维护。考虑在 [自定义管理器](/zh-hans/4.2/topics/db/managers/#custom-managers) 上实现一个辅助方法，既可以更新您的模型又可以执行其他逻辑，或者在使用模型信号之前 [覆盖模型方法](/zh-hans/4.2/topics/db/models/#overriding-model-methods)。

> **Warning**
>
> 这些信号中有很多是由各种模型方法发送的，比如 `__init__()` 或 [`save()`](/zh-hans/4.2/ref/models/instances/#django.db.models.Model.save)，你可以在自己的代码中覆盖这些方法。
>
> 如果你在模型上重写了这些方法，你必须调用父类的方法才能发送这些信号。
>
> 还需要注意的是，Django 默认将信号处理程序存储为弱引用，所以如果你的处理程序是一个本地函数，它可能会被垃圾回收。 为了防止这种情况，当你调用信号的 [`connect()`](/zh-hans/4.2/topics/signals/#django.dispatch.Signal.connect) 时，传入 `weak=False`。

> **Note**
>
> 模型信号 `sender` 模型可以在连接接收器时，通过指定其完整的应用程序标签进行惰性引用。例如，在 `polls` 应用程序中定义的 `Question` 模型可以被引用为 `'polls.Question'`。在处理循环导入依赖关系和可交换模型时，这种引用可以非常方便。

### `pre_init`

#### `django.db.models.signals.pre_init`

每当你实例化一个 Django 模型时，这个信号都会在模型的 `__init__()` 方法的开头发出。

用此信号发送的参数：

**`sender`**

  刚刚创建了一个实例的模型类。

**`args`**

  传递给 `__init__()` 的位置参数列表。

**`kwargs`**

  传递给 `__init__()` 的关键字参数字典。

例如，[教程](/zh-hans/4.2/intro/tutorial02/) 有这样一行：

```
q = Question(question_text="What's new?", pub_date=timezone.now())
```

发送给 [`pre_init`](#django.db.models.signals.pre_init) 处理程序的参数是：

| 参数 | 值 |
| --- | --- |
| `sender` | `Question` （类本身） |
| `args` | `[]` （一个空列表，因为没有向 `__init__()` 传递位置参数） |
| `kwargs` | `{'question_text': "What's new?",`<br>`'pub_date': datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=datetime.timezone.utc)}` |

### `post_init`

#### `django.db.models.signals.post_init`

和 pre\_init 一样，但这个是在 `__init__()` 方法完成后发送的。

用此信号发送的参数：

**`sender`**

  如上：刚刚创建了一个实例的模型类。

**`instance`**

  刚刚创建的模型的实际实例。

  > **Note**
  >
  > [`instance._state`](/zh-hans/4.2/ref/models/instances/#django.db.models.Model._state) 在发送 `post_init` 信号之前没有设置，所以 `_state` 属性总是有其默认值。例如，`_state.db` 是 `None`。

> **Warning**
>
> 出于性能考虑，你不应该在 `pre_init` 或 `post_init` 信号的接收者中执行查询，因为在查询集迭代期间，它们会对每个返回的实例执行。

### `pre_save`

#### `django.db.models.signals.pre_save`

这是在模型的 [`save()`](/zh-hans/4.2/ref/models/instances/#django.db.models.Model.save) 方法开始时发送的。

用此信号发送的参数：

**`sender`**

  模型类

**`instance`**

  实际被保存的实例。

**`raw`**

  一个布尔值；如果模型被保存的方式与原始数据一致（即在加载 [fixture](/zh-hans/4.2/topics/db/fixtures/#fixtures-explanation) 时），则为 `True`。在这种情况下，不应查询/修改数据库中的其他记录，因为数据库可能尚未处于一致状态。

**`using`**

  正在使用的数据库别名。

**`update_fields`**

  传递给 [`Model.save()`](/zh-hans/4.2/ref/models/instances/#django.db.models.Model.save) 的要更新的字段集，如果 `update_fields` 没有传递给 `save()`，则为 `None`。

### `post_save`

#### `django.db.models.signals.post_save`

就像 [`pre_save`](#django.db.models.signals.pre_save) 一样，但在 [`save()`](/zh-hans/4.2/ref/models/instances/#django.db.models.Model.save) 方法的最后发送。

用此信号发送的参数：

**`sender`**

  模型类

**`instance`**

  实际被保存的实例。

**`created`**

  一个布尔值；`True` 如果创建了一个新记录。

**`raw`**

  一个布尔值；如果模型被保存的方式与原始数据一致（即在加载 [fixture](/zh-hans/4.2/topics/db/fixtures/#fixtures-explanation) 时），则为 `True`。在这种情况下，不应查询/修改数据库中的其他记录，因为数据库可能尚未处于一致状态。

**`using`**

  正在使用的数据库别名。

**`update_fields`**

  传递给 [`Model.save()`](/zh-hans/4.2/ref/models/instances/#django.db.models.Model.save) 的要更新的字段集，如果 `update_fields` 没有传递给 `save()`，则为 `None`。

### `pre_delete`

#### `django.db.models.signals.pre_delete`

在模型的 `delete()` 方法和查询集的 [`delete()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.delete) 方法开始时发送。

用此信号发送的参数：

**`sender`**

  模型类

**`instance`**

  实际被删除的实例。

**`using`**

  正在使用的数据库别名。

**`origin`**

  > **New in Django 4.1**

  删除的起始点是一个 `Model` 或 `QuerySet` 类的实例。

### `post_delete`

#### `django.db.models.signals.post_delete`

就像 [`pre_delete`](#django.db.models.signals.pre_delete) 一样，但在模型的 `delete()` 方法和查询集的 [`delete()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.delete) 方法结束时发送。

用此信号发送的参数：

**`sender`**

  模型类

**`instance`**

  实际被删除的实例。

  请注意，该对象将不再在数据库中，所以要非常小心地处理这个实例。

**`using`**

  正在使用的数据库别名。

**`origin`**

  > **New in Django 4.1**

  删除的起始点是一个 `Model` 或 `QuerySet` 类的实例。

### `m2m_changed`

#### `django.db.models.signals.m2m_changed`

当一个模型实例上的 [`ManyToManyField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ManyToManyField) 被改变时发出。严格来说，这不是一个模型信号，因为它是由 [`ManyToManyField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ManyToManyField) 发送的，但由于它是对 [`pre_save`](#django.db.models.signals.pre_save)/[`post_save`](#django.db.models.signals.post_save) 和 [`pre_delete`](#django.db.models.signals.pre_delete)/[`post_delete`](#django.db.models.signals.post_delete) 的补充，当涉及到跟踪模型的变化时，它被包含在这里。

用此信号发送的参数：

**`sender`**

  中间模型类描述 [`ManyToManyField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ManyToManyField)。当定义了多对多字段时，这个类会自动创建；你可以使用多对多字段上的 `through` 属性来访问它。

**`instance`**

  多对多关系被更新的实例。这可以是 `sender` 的实例，或者是 [`ManyToManyField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ManyToManyField) 所关联的类的实例。

**`action`**

  表示对关系进行更新的类型的字符串。可以是以下类型之一：

  **`"pre_add"`**

    在一个或多个对象被添加到关系 *之前* 发送。

  **`"post_add"`**

    在一个或多个对象被添加到关系 *之后* 发送。

  **`"pre_remove"`**

    在一个或多个对象从关系中删除 *之前* 发送。

  **`"post_remove"`**

    在一个或多个对象从关系中删除 *之后* 发送。

  **`"pre_clear"`**

    在关系被清除 *之前* 发送。

  **`"post_clear"`**

    在关系被清除 *之后* 发送。

**`reverse`**

  表示关系的哪一面被更新（即被修改的是正向关系还是反向关系）。

**`model`**

  从关系中添加、删除或清除的对象的类别。

**`pk_set`**

  对于 `pre_add` 和 `post_add` 动作，这是一组将被或已经被添加到关系中的主键值。这可能是提交添加的值的一个子集，因为插入必须过滤现有的值，以避免数据库 `IntegrityError`。

  对于 `pre_remove` 和 `post_remove` 动作来说，这是一组被提交从关系中删除的主键值。这并不取决于这些值是否会被实际删除或已经被删除。特别是，不存在的值可能会被提交，并且会出现在 `pk_set` 中，即使它们对数据库没有影响。

  对于 `pre_clear` 和 `post_clear` 动作，是 `None`。

**`using`**

  正在使用的数据库别名。

例如，如果一个 `Pizza` 可以有多个 `Topping` 对象，模型如下：

```
class Topping(models.Model):
    # ...
    pass

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)
```

如果我们连接一个这样的处理程序：

```
from django.db.models.signals import m2m_changed

def toppings_changed(sender, **kwargs):
    # Do something
    pass

m2m_changed.connect(toppings_changed, sender=Pizza.toppings.through)
```

然后执行了类似以下操作：

```pycon
>>> p = Pizza.objects.create(...)
>>> t = Topping.objects.create(...)
>>> p.toppings.add(t)
```

发送给 [`m2m_changed`](#django.db.models.signals.m2m_changed) 处理程序的参数（在上面的例子中，`toppings_changed`）将是：

| 参数 | 值 |
| --- | --- |
| `sender` | `Pizza.toppings.through` （中间的 m2m 类） |
| `instance` | `p` （被修改的 `Pizza` 实例） |
| `action` | `"pre_add"` （后面是一个单独的信号 `"post_add"`） |
| `reverse` | `False` （`Pizza` 包含 [`ManyToManyField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ManyToManyField)，所以这个调用修改了前向关系） |
| `model` | `Topping` （添加到 `Pizza` 中的对象类别） |
| `pk_set` | `{t.id}` （因为只有 `Topping t` 被添加到关系中） |
| `using` | `"default"` （因为默认的路由器在这里发送写入） |

如果我们接下来做了类似以下的操作：

```pycon
>>> t.pizza_set.remove(p)
```

发送给 [`m2m_changed`](#django.db.models.signals.m2m_changed) 处理程序的参数将是：

| 参数 | 值 |
| --- | --- |
| `sender` | `Pizza.toppings.through` （中间的 m2m 类） |
| `instance` | `t` （正在修改的 `Topping` 实例） |
| `action` | `"pre_remove"` （后面是一个单独的信号 `"post_remove"`） |
| `reverse` | `True` （`Pizza` 包含 [`ManyToManyField`](/zh-hans/4.2/ref/models/fields/#django.db.models.ManyToManyField)，所以这个调用修改了反向关系） |
| `model` | `Pizza` （从 `Topping` 中删除的对象类别） |
| `pk_set` | `{p.id}` （因为只有 `Pizza p` 被从关系中删除） |
| `using` | `"default"` （因为默认的路由器在这里发送写入） |

### `class_prepared`

#### `django.db.models.signals.class_prepared`

每当模型类被 "准备" 时发送，也就是说，一旦模型已经被定义并在 Django 的模型系统中注册。Django 在内部使用这个信号；它通常不在第三方应用程序中使用。

由于这个信号是在应用注册表填充过程中发出的，而 [`AppConfig.ready()`](/zh-hans/4.2/ref/applications/#django.apps.AppConfig.ready) 是在应用注册表完全填充后运行的，所以不能在该方法中连接接收器。一种可能是用 `AppConfig.__init__()` 来代替连接它们，注意不要导入模型或触发对应用注册表的调用。

用此信号发送的参数：

**`sender`**

  刚刚准备好的模型类。

## 管理信号

[django-admin](/zh-hans/4.2/ref/django-admin/) 发出的信号。

### `pre_migrate`

#### `django.db.models.signals.pre_migrate`

由 [`migrate`](/zh-hans/4.2/ref/django-admin/#django-admin-migrate) 命令在开始安装应用程序之前发出。对于缺乏 `models` 模块的应用程序，它不会发出。

用此信号发送的参数：

**`sender`**

  一个 [`AppConfig`](/zh-hans/4.2/ref/applications/#django.apps.AppConfig) 实例，用于即将迁移／同步的应用程序。

**`app_config`**

  同 `sender`。

**`verbosity`**

  指示 `manage.py` 在屏幕上打印多少信息。有关详细信息，请参阅 [`--verbosity`](/zh-hans/4.2/ref/django-admin/#cmdoption-verbosity) 标志。

  监听 [`pre_migrate`](#django.db.models.signals.pre_migrate) 的函数应该根据这个参数的值来调整它们向屏幕输出的内容。

**`interactive`**

  如果 `interactive` 为 `True`，则可以安全地提示用户在命令行上输入东西。如果 `interactive` 为 `False`，则监听该信号的函数不应试图提示任何东西。

  例如 [`django.contrib.auth`](/zh-hans/4.2/topics/auth/#module-django.contrib.auth) 应用只有在 `interactive` 为 `True` 时才会提示创建超级用户。

**`stdout`**

  一个类似于流的对象，用于重定向详细的输出。

**`using`**

  命令将运行的数据库的别名。

**`plan`**

  将用于迁移运行的迁移计划。虽然计划不是公开的 API，但这允许在极少数情况下有必要知道计划。计划是一个由二元元组组成的列表，第一项是迁移类的实例，第二项显示迁移是否被回滚（`True`）或应用（`False`）。

**`apps`**

  [`Apps`](/zh-hans/4.2/ref/applications/#module-django.apps) 的实例，包含迁移运行前的项目状态。它应该代替全局 `apps` 注册表来检索你要执行操作的模型。

### `post_migrate`

#### `django.db.models.signals.post_migrate`

在 [`migrate`](/zh-hans/4.2/ref/django-admin/#django-admin-migrate) （即使没有运行迁移）和 [`flush`](/zh-hans/4.2/ref/django-admin/#django-admin-flush) 命令结束时发出。对于缺乏 `models` 模块的应用程序，它不会被发出。

该信号的处理者不能进行数据库模式的改变，因为如果在 [`migrate`](/zh-hans/4.2/ref/django-admin/#django-admin-migrate) 命令期间运行 [`flush`](/zh-hans/4.2/ref/django-admin/#django-admin-flush) 命令，可能会导致 [`flush`](/zh-hans/4.2/ref/django-admin/#django-admin-flush) 命令失败。

用此信号发送的参数：

**`sender`**

  一个 `AppConfig` 实例，用于刚刚安装的应用程序。

**`app_config`**

  同 `sender`。

**`verbosity`**

  指示 `manage.py` 在屏幕上打印多少信息。有关详细信息，请参阅 [`--verbosity`](/zh-hans/4.2/ref/django-admin/#cmdoption-verbosity) 标志。

  监听 [`post_migrate`](#django.db.models.signals.post_migrate) 的函数应该根据这个参数的值来调整它们向屏幕输出的内容。

**`interactive`**

  如果 `interactive` 为 `True`，则可以安全地提示用户在命令行上输入东西。如果 `interactive` 为 `False`，则监听该信号的函数不应试图提示任何东西。

  例如 [`django.contrib.auth`](/zh-hans/4.2/topics/auth/#module-django.contrib.auth) 应用只有在 `interactive` 为 `True` 时才会提示创建超级用户。

**`stdout`**

  一个类似于流的对象，用于重定向详细的输出。

**`using`**

  用于同步的数据库别名。默认为 `default` 数据库。

**`plan`**

  迁移运行时使用的迁移计划。虽然计划不是公开的 API，但这允许在极少数情况下有必要知道计划。计划是一个由二元元组组成的列表，第一项是迁移类的实例，第二项显示迁移是否被回滚（`True`）或应用（`False`）。

**`apps`**

  `Apps` 的一个实例，包含迁移运行后项目的状态。它应该代替全局的 `apps` 注册表来检索你要执行操作的模型。

例如，你可以在一个 `AppConfig` 中注册一个回调，像这样：

```
from django.apps import AppConfig
from django.db.models.signals import post_migrate

def my_callback(sender, **kwargs):
    # Your specific logic here
    pass

class MyAppConfig(AppConfig):
    ...

    def ready(self):
        post_migrate.connect(my_callback, sender=self)
```

> **Note**
>
> 如果你提供了一个 [`AppConfig`](/zh-hans/4.2/ref/applications/#django.apps.AppConfig) 实例作为发送者参数，请确保该信号在 [`ready()`](/zh-hans/4.2/ref/applications/#django.apps.AppConfig.ready) 中注册。`AppConfig` 会被重新创建，用于使用修改过的 [`INSTALLED_APPS`](/zh-hans/4.2/ref/settings/#std-setting-INSTALLED_APPS) 集合运行的测试（例如当配置被覆盖时），并且这种信号应该为每个新的 `AppConfig` 实例连接。

## 请求／响应信号

核心框架处理请求时发出的信号。

> **Warning**
>
> 信号可能会使您的代码更难维护。在使用请求/响应信号之前，考虑 [使用中间件](/zh-hans/4.2/topics/http/middleware/)。

### `request_started`

#### `django.core.signals.request_started`

当 Django 开始处理一个 HTTP 请求时发送。

用此信号发送的参数：

**`sender`**

  处理程序类 —— 例如 `django.core.handlers.wsgi.wsgiHandler` —— 处理该请求。

**`environ`**

  向请求提供的 `environ` 字典。

### `request_finished`

#### `django.core.signals.request_finished`

当 Django 完成向客户端发送 HTTP 响应时发送。

用此信号发送的参数：

**`sender`**

  处理程序类，同上。

### `got_request_exception`

#### `django.core.signals.got_request_exception`

当 Django 在处理一个传入的 HTTP 请求时遇到异常时，就会发出这个信号。

用此信号发送的参数：

**`sender`**

  未使用（总是 `None`）。

**`request`**

  [`HttpRequest`](/zh-hans/4.2/ref/request-response/#django.http.HttpRequest) 对象。

## 测试信号

只有当 [运行测试](/zh-hans/4.2/topics/testing/overview/#running-tests) 时才会发出信号。

### `setting_changed`

#### `django.test.signals.setting_changed`

当通过 `django.test.TestCase.settings()` 上下文管理器或 [`django.test.override_settings()`](/zh-hans/4.2/topics/testing/tools/#django.test.override_settings) 装饰器／上下文管理器改变配置值时，会发出这个信号。

它实际上被发送了两次：当应用新的值时（"setup"）和当恢复原始值时（"drawdown"）。使用 `enter` 参数来区分这两种情况。

你也可以从 `django.core.signals` 导入这个信号，以避免在非测试情况下从 `django.test` 导入。

用此信号发送的参数：

**`sender`**

  配置处理程序。

**`setting`**

  配置的名称。

**`value`**

  更改后的配置值。对于最初不存在的配置，在 "teardown" 阶段，`value` 是 `None`。

**`enter`**

  一个布尔值；`True` 如果配置被应用，`False` 如果恢复。

### `template_rendered`

#### `django.test.signals.template_rendered`

当测试系统渲染一个模板时发出。这个信号在 Django 服务器正常运行时不会发出，只有在测试时才会发出。

用此信号发送的参数：

**`sender`**

  被渲染的 [`Template`](/zh-hans/4.2/ref/templates/api/#django.template.Template) 对象。

**`template`**

  与发送器相同

**`context`**

  渲染模板的 [`Context`](/zh-hans/4.2/ref/templates/api/#django.template.Context)。

## 数据库包装器

当数据库连接启动时，数据库包装器发出的信号。

### `connection_created`

#### `django.db.backends.signals.connection_created`

当数据库包装器与数据库进行初始连接时发送。 如果你想向 SQL 后端发送任何连接后的命令，这一点特别有用。

用此信号发送的参数：

**`sender`**

  数据库封装类 —— 即 `django.db.backends.postgresql.DatabaseWrapper` 或 `django.db.backends.mysql.DatabaseWrapper` 等。

**`connection`**

  打开的数据库连接。这在多数据库配置中可以用来区分不同数据库的连接信号。
