---
title: "约束参考"
version: 4.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/4.2/ref/models/constraints/
canonical: https://djangodocs.dev/zh-hans/4.2/ref/models/constraints/
---
# 约束参考

本模块中定义的类可以创建数据库约束。它们被添加到模型中 `Meta.constraints` 选项中。

> **引用内置约束**
>
> 约束是在 `django.db.models.constraint` 中定义的，但为了方便，它们被导入到 [`django.db.models`](/zh-hans/4.2/topics/db/models/#module-django.db.models) 中。标准的惯例是使用 `from django.db import models` 作为 `models.<Foo>Constraint`。

> **抽象基类中的约束**
>
> 你必须始终为约束指定一个唯一的名称。因此，你通常不能在抽象基类上指定一个约束，因为 `Meta.craces` 选项是由子类继承的，每次的属性值（包括 `name`）都完全相同。为了解决名称碰撞的问题，名称的一部分可能包含 `'%(app_label)s'` 和 `'%(class)s'`，它们分别被具体模型的小写应用标签和类名所代替。例如 `CheckConstraint(check=Q(age__gte=18)，name='%(app_label)s_%(class)s_is_adult')`。

> **约束的验证**
>
> 约束在 [模型验证](/zh-hans/4.2/ref/models/instances/#validating-objects) 过程中进行检查。

> **对于 JSONField 的约束验证**
>
> 包含 [`JSONField`](/zh-hans/4.2/ref/models/fields/#django.db.models.JSONField) 的约束可能不会引发验证错误，因为键、索引和路径转换具有许多与数据库相关的注意事项。这个问题 [可能在以后被完全支持](https://code.djangoproject.com/ticket/34059)。
>
> 您应该始终检查是否有来自 `django.db.models` 记录器的日志消息，例如 *"在...上调用 check() 时出现了数据库错误"*，以确认它已正确验证。

> **Changed in Django 4.1**
>
> 在旧版本中，约束在模型验证期间不会被检查。

## `BaseConstraint`

#### `class BaseConstraint(name, violation_error_message=None)`

所有约束的基类。子类必须实现 `constraint_sql()`, `create_sql()`, `remove_sql()` 和 `validate()` 方法。

所有约束都有以下共同的参数：

### `name`

#### `BaseConstraint.name`

约束的名称。你必须始终为约束指定一个唯一的名称。

### `violation_error_message`

> **New in Django 4.1**

#### `BaseConstraint.violation_error_message`

在 [模型验证](/zh-hans/4.2/ref/models/instances/#validating-objects) 过程中引发 `ValidationError` 时使用的错误消息。默认为 `"违反了约束“%(name)s”"`。

### `validate()`

> **New in Django 4.1**

#### `BaseConstraint.validate(model, instance, exclude=None, using=DEFAULT_DB_ALIAS)`

验证在 `model` 上定义的约束是否在 `instance` 上被遵守。这将在数据库上执行一个查询，以确保该约束被遵守。如果需要使用 `exclude` 列表中的字段来验证约束，则会忽略该约束。

如果违反了约束，则引发 `ValidationError`。

这个方法必须由子类来实现。

## `CheckConstraint`

#### `class CheckConstraint(* (Keyword-only parameters separator (PEP 3102)), check, name, violation_error_message=None)`

在数据库中创建一个检查约束

### `check`

#### `CheckConstraint.check`

一个 [`Q`](/zh-hans/4.2/ref/models/querysets/#django.db.models.Q) 对象或布尔值 [`Expression`](/zh-hans/4.2/ref/models/expressions/#django.db.models.Expression)，它指定了你要强制约束的检查。

例如，`CheckConstraint(check=Q(age__gte=18), name='age_gte_18')` 确保年龄字段永远不小于 18。

> **Oracle**
>
> 在 Oracle 上对可空字段进行检查时，必须包含一个允许 `NULL` 值的条件，以使 [`validate()`](#django.db.models.BaseConstraint.validate) 的行为与检查约束验证相同。例如，如果 `age` 是可空字段：
>
> ```
> CheckConstraint(check=Q(age__gte=18) | Q(age__isnull=True), name="age_gte_18")
> ```

> **Changed in Django 4.1**
>
> 添加了\`\`violation\_error\_message\`\` 参数。

## `UniqueConstraint`

#### `class UniqueConstraint(*expressions, fields=(), name=None, condition=None, deferrable=None, include=None, opclasses=(), violation_error_message=None)`

在数据库中创建一个唯一约束。

### `expressions`

#### `UniqueConstraint.expressions`

位置参数 `*expressions` 允许在表达式和数据库函数上创建功能性唯一约束。

例子：

```
UniqueConstraint(Lower("name").desc(), "category", name="unique_lower_name_category")
```

在降序中的 `name` 字段的小写值和默认升序中的 `category` 字段上创建了一个唯一约束。

功能性唯一约束具有与 [`Index.expressions`](/zh-hans/4.2/ref/models/indexes/#django.db.models.Index.expressions) 相同的数据库限制。

### `fields`

#### `UniqueConstraint.fields`

一个字段名的列表，它指定了你要强制约束的唯一列集。

例如，`UniqueConstraint(field=['room', 'date'], name='unique_booking')` 确保每个房间在每个日期只能被预订一次。

### `condition`

#### `UniqueConstraint.condition`

一个 [`Q`](/zh-hans/4.2/ref/models/querysets/#django.db.models.Q) 对象，用于指定你想要强制执行的约束条件。

例子：

```
UniqueConstraint(fields=["user"], condition=Q(status="DRAFT"), name="unique_draft_user")
```

确保每个用户只有一份草稿。

这些条件与 [`Index.condition`](/zh-hans/4.2/ref/models/indexes/#django.db.models.Index.condition) 具有相同的数据库限制。

### `deferrable`

#### `UniqueConstraint.deferrable`

设置该参数，可创建一个可推迟的唯一约束。接受的值是 `Deferrable.DEFERRED` 或 `Deferrable.IMMEDIATE`。例如：

```
from django.db.models import Deferrable, UniqueConstraint

UniqueConstraint(
    name="unique_order",
    fields=["order"],
    deferrable=Deferrable.DEFERRED,
)
```

默认情况下，约束条件是不推迟的。推迟的约束条件在事务结束前不会被强制执行。即时约束将在每条命令后立即执行。

> **MySQL，MariaDB 和 SQLite。**
>
> 在 MySQL、MariaDB 和 SQLite 上，可推迟的唯一约束被忽略，因为它们都不支持。

> **Warning**
>
> 推迟的唯一约束可能导致 [性能惩罚](https://www.postgresql.org/docs/current/sql-createtable.html#id-1.9.3.85.9.4) 。

### `include`

#### `UniqueConstraint.include`

一个包含在覆盖的唯一索引中的字段名称的列表或元组，作为非键列。这允许只用索引扫描，用于只选择包含的字段（ [`include`](#django.db.models.UniqueConstraint.include) ）和只过滤唯一字段（ [`fields`](#django.db.models.UniqueConstraint.fields) ）的查询。

例子：

```
UniqueConstraint(name="unique_booking", fields=["room", "date"], include=["full_name"])
```

将允许对 `room` 和 `date` 进行过滤，也可以选择 `full_name`，同时只从索引中获取数据。

`include` 只在 PostgreSQL 上支持。

非关键列具有与 [`Index.include`](/zh-hans/4.2/ref/models/indexes/#django.db.models.Index.include) 相同的数据库限制。

### `opclasses`

#### `UniqueConstraint.opclasses`

用于此唯一索引的 [PostgreSQL 操作符类别](https://www.postgresql.org/docs/current/indexes-opclass.html) 的名称。如果需要自定义操作符类别，必须为索引中的每个字段提供一个。

例子：

```
UniqueConstraint(
    name="unique_username", fields=["username"], opclasses=["varchar_pattern_ops"]
)
```

使用 `varchar_pattern_ops` 在 `username` 上创建了一个唯一索引。

`opclasses` 对于 PostgreSQL 以外的数据库来说是被忽略的。

### `violation_error_message`

> **New in Django 4.1**

#### `UniqueConstraint.violation_error_message`

在 [模型验证](/zh-hans/4.2/ref/models/instances/#validating-objects) 期间引发 `ValidationError` 时使用的错误消息。默认为 [`BaseConstraint.violation_error_message`](#django.db.models.BaseConstraint.violation_error_message)。

这个消息 *不会* 用于没有 [`condition`](#django.db.models.UniqueConstraint.condition) 且带有 [`fields`](#django.db.models.UniqueConstraint.fields) 的 [`UniqueConstraint`](#django.db.models.UniqueConstraint)。这样的 [`UniqueConstraint`](#django.db.models.UniqueConstraint) 显示与使用 [`Field.unique`](/zh-hans/4.2/ref/models/fields/#django.db.models.Field.unique) 或 [`Meta.unique_together`](/zh-hans/4.2/ref/models/options/#django.db.models.Options.constraints) 定义的约束相同的消息。
