---
title: "PostgreSQL 特有模型字段"
version: 5.2
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/5.2/ref/contrib/postgres/fields/
canonical: https://djangodocs.dev/zh-hans/5.2/ref/contrib/postgres/fields/
---
# PostgreSQL 特有模型字段

所有这些字段都可以从 `django.contrib.postgres.field` 模块中获得。

## 对这些字段进行索引

[`Index`](/zh-hans/5.2/ref/models/indexes/#django.db.models.Index) 和 [`Field.db_index`](/zh-hans/5.2/ref/models/fields/#django.db.models.Field.db_index) 都创建了一个 B 树索引，在查询复杂的数据类型时并不是特别有用。像 [`GinIndex`](/zh-hans/5.2/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.GinIndex) 和 [`GistIndex`](/zh-hans/5.2/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.GistIndex) 这样的索引比较适合，不过索引的选择取决于你使用的查询。一般来说，GiST 可能是 [range 字段](#range-fields) 和 [`HStoreField`](#django.contrib.postgres.fields.HStoreField) 的好选择，而 GIN 可能对 [`ArrayField`](#django.contrib.postgres.fields.ArrayField) 有帮助。

## `ArrayField`

#### `class ArrayField(base_field, size=None, **options)`

一个用于存储数据列表的字段。大多数字段类型都可以使用，你可以通过另一个字段实例作为 [`base_field`](#django.contrib.postgres.fields.ArrayField.base_field)。你也可以指定一个 [`size`](#django.contrib.postgres.fields.ArrayField.size)。`ArrayField` 可以嵌套来存储多维数组。

如果你给字段一个 [`default`](/zh-hans/5.2/ref/models/fields/#django.db.models.Field.default)，确保它是一个可调用对象，比如 `list` （对于一个空的默认值），或者一个返回一个列表的可调用对象（比如一个函数）。错误地使用 `default=[]` 会创建一个可变的默认值，这个默认值在 `ArrayField` 的所有实例之间共享。

#### `base_field`

这是一个必要的参数。

Specifies the underlying data type and behavior for the array. It
should be an instance of a subclass of
[`Field`](/zh-hans/5.2/ref/models/fields/#django.db.models.Field). For example, it could be an
[`IntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.IntegerField) or a
[`CharField`](/zh-hans/5.2/ref/models/fields/#django.db.models.CharField). Most field types are permitted,
with the exception of those handling relational data
([`ForeignKey`](/zh-hans/5.2/ref/models/fields/#django.db.models.ForeignKey),
[`OneToOneField`](/zh-hans/5.2/ref/models/fields/#django.db.models.OneToOneField) and
[`ManyToManyField`](/zh-hans/5.2/ref/models/fields/#django.db.models.ManyToManyField)) and file fields
([`FileField`](/zh-hans/5.2/ref/models/fields/#django.db.models.FileField) and
[`ImageField`](/zh-hans/5.2/ref/models/fields/#django.db.models.ImageField)).

可以嵌套数组字段——你可以指定一个 `ArrayField` 的实例作为 `base_field`。例如：

```
from django.contrib.postgres.fields import ArrayField
from django.db import models

class ChessBoard(models.Model):
    board = ArrayField(
        ArrayField(
            models.CharField(max_length=10, blank=True),
            size=8,
        ),
        size=8,
    )
```

数据库和模型之间的值的转换、数据和配置的验证以及序列化都是委托给底层基础字段的。

#### `size`

这是一个可选的参数。

如果传入，数组将有一个指定的最大大小。这将被传递给数据库，尽管 PostgreSQL 目前并没有强制执行这个限制。

> **Note**
>
> 嵌套 `ArrayField` 时，无论是否使用 `size` 参数，PostgreSQL 都要求数组为矩形：
>
> ```
> from django.contrib.postgres.fields import ArrayField
> from django.db import models
>
>
> class Board(models.Model):
>     pieces = ArrayField(ArrayField(models.IntegerField()))
>
>
> # Valid
> Board(
>     pieces=[
>         [2, 3],
>         [2, 1],
>     ]
> )
>
> # Not valid
> Board(
>     pieces=[
>         [2, 3],
>         [2],
>     ]
> )
> ```
>
> 如果需要不规则的形状，则应将底层字段设为 null，并将值用 `None` 填充。

### 查询 `ArrayField`

[`ArrayField`](#django.contrib.postgres.fields.ArrayField) 有许多自定义的查找和转换。我们将使用下面的示例模型：

```
from django.contrib.postgres.fields import ArrayField
from django.db import models

class Post(models.Model):
    name = models.CharField(max_length=200)
    tags = ArrayField(models.CharField(max_length=200), blank=True)

    def __str__(self):
        return self.name
```

#### `contains`

[`ArrayField`](#django.contrib.postgres.fields.ArrayField) 上重写了 [`contains`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-contains) 查询。返回的对象将是那些传递的值是数据的子集的对象。它使用 SQL 运算符 `@>`。例如：

```pycon
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])

>>> Post.objects.filter(tags__contains=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__contains=["django"])
<QuerySet [<Post: First post>, <Post: Third post>]>

>>> Post.objects.filter(tags__contains=["django", "thoughts"])
<QuerySet [<Post: First post>]>
```

#### `contained_by`

这是 [`contains`](#std-fieldlookup-arrayfield.contains) 查询的反向操作 - 返回的对象将是那些数据是传递的值的子集的对象。它使用 SQL 运算符 `<@`。例如：

```pycon
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])

>>> Post.objects.filter(tags__contained_by=["thoughts", "django"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__contained_by=["thoughts", "django", "tutorial"])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
```

#### `overlap`

返回数据与传递的值共享任何结果的对象。使用 SQL 运算符 `&&`。例如：

```pycon
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts", "tutorial"])
>>> Post.objects.create(name="Third post", tags=["tutorial", "django"])

>>> Post.objects.filter(tags__overlap=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__overlap=["thoughts", "tutorial"])
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>

>>> Post.objects.filter(tags__overlap=Post.objects.values_list("tags"))
<QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>
```

#### `len`

返回数组的长度。之后可用的查询与 [`IntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.IntegerField) 相同。例如：

```pycon
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])

>>> Post.objects.filter(tags__len=1)
<QuerySet [<Post: Second post>]>
```

#### 索引转换

Index 转换将索引转换为数组。可以使用任何非负整数。如果超过数组的 [`size`](#django.contrib.postgres.fields.ArrayField.size)，则不会出现错误。转换后可用的查询是来自 [`base_field`](#django.contrib.postgres.fields.ArrayField.base_field) 的查询。例如：

```pycon
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])

>>> Post.objects.filter(tags__0="thoughts")
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__1__iexact="Django")
<QuerySet [<Post: First post>]>

>>> Post.objects.filter(tags__276="javascript")
<QuerySet []>
```

> **Note**
>
> PostgreSQL 在编写原始 SQL 时，对数组字段使用基于 1 的索引。然而这些索引和 [`slices`](#std-fieldlookup-arrayfield.slice) 中使用的索引使用基于 0 的索引，以与 Python 保持一致。

#### 切片转换

Slice 转换获取数组的一个切片。可以使用两个非负整数，用一个下划线分隔。转换后可用的查询不会改变。例如：

```pycon
>>> Post.objects.create(name="First post", tags=["thoughts", "django"])
>>> Post.objects.create(name="Second post", tags=["thoughts"])
>>> Post.objects.create(name="Third post", tags=["django", "python", "thoughts"])

>>> Post.objects.filter(tags__0_1=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__0_2__contains=["thoughts"])
<QuerySet [<Post: First post>, <Post: Second post>]>
```

> **Note**
>
> PostgreSQL 在编写原始 SQL 时，对数组字段使用基于 1 的索引。然而这些分片和 [`indexes`](#std-fieldlookup-arrayfield.index) 中使用的分片使用基于 0 的索引，以与 Python 保持一致。

> **带索引和切片的多维数组**
>
> PostgreSQL 在多维数组上使用索引和切片时，有一些相当神秘的行为。使用索引向下到达最终的底层数据总是可行的，但是大多数其他的切片在数据库层面的行为很奇怪，不能被 Django 以逻辑的、一致的方式支持。

## `HStoreField`

#### `class HStoreField(**options)`

一个用于存储键值对的字段。使用的 Python 数据类型是 `dict`。键必须是字符串，值可以是字符串或空值（Python 中的 `None`）。

要使用该字段，你需要：

1. 在你的 [`INSTALLED_APPS`](/zh-hans/5.2/ref/settings/#std-setting-INSTALLED_APPS) 中增加 `'django.contrib.postgres'`。
2. 在 PostgreSQL 中 [安装 hstore 扩展](/zh-hans/5.2/ref/contrib/postgres/operations/#create-postgresql-extensions)。

如果你跳过第一步，你会看到一个错误，比如 `can't adapt type 'dict'`，如果你跳过第二步，你会看到 `type "hstore" does not exist`。

> **Note**
>
> 在某些情况下，可能需要要求或限制对某个字段有效的键。这可以使用 [`KeysValidator`](/zh-hans/5.2/ref/contrib/postgres/validators/#django.contrib.postgres.validators.KeysValidator) 来完成。

### 查询 `HStoreField`

除了按键查询的功能外，`HStoreField` 还有一些自定义查询功能。

我们将使用以下示例模型：

```
from django.contrib.postgres.fields import HStoreField
from django.db import models

class Dog(models.Model):
    name = models.CharField(max_length=200)
    data = HStoreField()

    def __str__(self):
        return self.name
```

#### 键查找

要根据给定的键查询，您可以将该键用作查找名称：

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie"})

>>> Dog.objects.filter(data__breed="collie")
<QuerySet [<Dog: Meg>]>
```

您可以在键查找后链接其他查询：

```pycon
>>> Dog.objects.filter(data__breed__contains="l")
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
```

或者使用 `F()` 表达式来注释一个键值。例如：

```pycon
>>> from django.db.models import F
>>> rufus = Dog.objects.annotate(breed=F("data__breed"))[0]
>>> rufus.breed
'labrador'
```

如果你想查询的键与另一个查找的名称冲突，你需要使用 [`hstorefield.contains`](#std-fieldlookup-hstorefield.contains) 查找来代替。

> **Note**
>
> 关键词转换也可以与以下链式进行： [`contains`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-contains)、[`icontains`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-icontains)、[`endswith`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-endswith)、[`iendswith`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-iendswith)、[`iexact`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-iexact)、[`regex`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-regex)、[`iregex`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-iregex)、[`startswith`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-startswith) 和 [`istartswith`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-istartswith) 查询。

> **Warning**
>
> 由于任何字符串都可能是 hstore 值中的一个键，因此除了下面列出的以外的任何查询都将被解释为键查询。不会出现任何错误。要格外小心输入错误，并始终检查你的查询是否按照你的意图工作。

#### `contains`

[`HStoreField`](#django.contrib.postgres.fields.HStoreField) 上重写了 [`contains`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-contains) 查询。返回的对象是那些给定的键值对字典都包含在字段中的对象。它使用 SQL 运算符 `@>`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})

>>> Dog.objects.filter(data__contains={"owner": "Bob"})
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>

>>> Dog.objects.filter(data__contains={"breed": "collie"})
<QuerySet [<Dog: Meg>]>
```

#### `contained_by`

这是 [`contains`](#std-fieldlookup-hstorefield.contains) 查询的反向操作 - 返回的对象将是那些对象的键值对是传递值中的子集。它使用 SQL 运算符 `<@`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})

>>> Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"})
<QuerySet [<Dog: Meg>, <Dog: Fred>]>

>>> Dog.objects.filter(data__contained_by={"breed": "collie"})
<QuerySet [<Dog: Fred>]>
```

#### `has_key`

返回包含给定键的数据的对象。使用 SQL 运算符 `?`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__has_key="owner")
<QuerySet [<Dog: Meg>]>
```

#### `has_any_keys`

返回其中任何给定键存在于数据中的对象。使用 SQL 运算符 `?|`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"owner": "Bob"})
>>> Dog.objects.create(name="Fred", data={})

>>> Dog.objects.filter(data__has_any_keys=["owner", "breed"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
```

#### `has_keys`

返回其中所有给定键都存在于数据中的对象。使用 SQL 运算符 `?&`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__has_keys=["breed", "owner"])
<QuerySet [<Dog: Meg>]>
```

#### `keys`

返回键数组与给定值相等的对象。请注意，顺序不能保证可靠，因此此转换主要用于与 [`ArrayField`](#django.contrib.postgres.fields.ArrayField) 上的查找一起使用。使用 SQL 函数 `akeys()`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={"toy": "bone"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__keys__overlap=["breed", "toy"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
```

#### `values`

返回值数组与给定值相等的对象。请注意，顺序不能保证可靠，因此此转换主要用于与 [`ArrayField`](#django.contrib.postgres.fields.ArrayField) 上的查找一起使用。使用 SQL 函数 `avals()`。例如：

```pycon
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})

>>> Dog.objects.filter(data__values__contains=["collie"])
<QuerySet [<Dog: Meg>]>
```

## 范围字段

有五种范围字段类型，对应 PostgreSQL 中内置的范围类型。这些字段用来存储一个范围的值，例如一个事件的开始和结束时间戳，或者一个活动适合的年龄范围。

所有的范围字段在 Python 中都会翻译成 [psycopg Range 对象](https://www.psycopg.org/psycopg3/docs/basic/pgtypes.html#adapt-range)，但如果不需要边界信息，也可以接受元组作为输入。默认是包含下界，不包含上界，即 `[)` （有关 [不同边界](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO) 的详细信息，请参阅 PostgreSQL 文档）。对于非离散范围字段（例如 [`DateTimeRangeField`](#django.contrib.postgres.fields.DateTimeRangeField) 和 [`DecimalRangeField`](#django.contrib.postgres.fields.DecimalRangeField)），可以使用 `default_bounds` 参数更改默认边界。

> **PostgreSQL normalizes a range with no points to the empty range**
>
> A range with equal values specified for an included lower bound and an
> excluded upper bound, such as `Range(datetime.date(2005, 6, 21),
> datetime.date(2005, 6, 21))` or `[4, 4)`, has no points. PostgreSQL will
> normalize the value to empty when saving to the database, and the original
> bound values will be lost. See the [PostgreSQL documentation for details](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO).

### `IntegerRangeField`

#### `class IntegerRangeField(**options)`

存储一组整数范围。基于 [`IntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.IntegerField)。在数据库中由 `int4range` 表示，在 Python 中由 `django.db.backends.postgresql.psycopg_any.NumericRange` 表示。

无论在保存数据时指定的边界是什么，PostgreSQL 总是以规范的形式返回一个包括下限和排除上限的范围，即 `[)`。

### `BigIntegerRangeField`

#### `class BigIntegerRangeField(**options)`

存储一组大整数范围。基于 [`BigIntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BigIntegerField)。在数据库中由 `int8range` 表示，在 Python 中由 `django.db.backends.postgresql.psycopg_any.NumericRange` 表示。

无论在保存数据时指定的边界是什么，PostgreSQL 总是以规范的形式返回一个包括下限和排除上限的范围，即 `[)`。

### `DecimalRangeField`

#### `class DecimalRangeField(default_bounds='[)', **options)`

存储一组浮点数值范围。基于 [`DecimalField`](/zh-hans/5.2/ref/models/fields/#django.db.models.DecimalField)。在数据库中由 `numrange` 表示，在 Python 中由 `django.db.backends.postgresql.psycopg_any.NumericRange` 表示。

#### `default_bounds`

可选。列表和元组输入的 `bounds` 值。默认为包含下界，不包含上界，即 `[)` （有关 [不同边界](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO) 的详细信息，请参阅 PostgreSQL 文档）。`default_bounds` 不用于 `django.db.backends.postgresql.psycopg_any.NumericRange` 输入。

### `DateTimeRangeField`

#### `class DateTimeRangeField(default_bounds='[)', **options)`

存储一组时间戳范围。基于 [`DateTimeField`](/zh-hans/5.2/ref/models/fields/#django.db.models.DateTimeField)。在数据库中由 `tstzrange` 表示，在 Python 中由 `django.db.backends.postgresql.psycopg_any.DateTimeTZRange` 表示。

#### `default_bounds`

可选。列表和元组输入的 `bounds` 值。默认为包含下界，不包含上界，即 `[)` （有关 [不同边界](https://www.postgresql.org/docs/current/rangetypes.html#RANGETYPES-IO) 的详细信息，请参阅 PostgreSQL 文档）。`default_bounds` 不用于 `django.db.backends.postgresql.psycopg_any.DateTimeTZRange` 输入。

### `DateRangeField`

#### `class DateRangeField(**options)`

存储一组日期范围。基于 [`DateField`](/zh-hans/5.2/ref/models/fields/#django.db.models.DateField)。在数据库中由 `daterange` 表示，在 Python 中由 `django.db.backends.postgresql.psycopg_any.DateRange` 表示。

无论在保存数据时指定的边界是什么，PostgreSQL 总是以规范的形式返回一个包括下限和排除上限的范围，即 `[)`。

### 查询范围字段

对于范围字段，有许多自定义查找和转换。它们适用于所有上述字段，但我们将使用以下示例模型：

```
from django.contrib.postgres.fields import IntegerRangeField
from django.db import models

class Event(models.Model):
    name = models.CharField(max_length=200)
    ages = IntegerRangeField()
    start = models.DateTimeField()

    def __str__(self):
        return self.name
```

我们还将使用以下示例对象：

```pycon
>>> import datetime
>>> from django.utils import timezone
>>> now = timezone.now()
>>> Event.objects.create(name="Soft play", ages=(0, 10), start=now)
>>> Event.objects.create(
...     name="Pub trip", ages=(21, None), start=now - datetime.timedelta(days=1)
... )
```

和 `NumericRange`：

```
>>> from django.db.backends.postgresql.psycopg_any import NumericRange
```

#### 包含函数

与其他 PostgreSQL 字段一样，有三个标准的包含运算符。`contains`、`contained_by` 和 `overlap`，分别使用 SQL 运算符 `@>`、`<@` 和 `&&`。

##### `contains`

```
>>> Event.objects.filter(ages__contains=NumericRange(4, 5))
<QuerySet [<Event: Soft play>]>
```

##### `contained_by`

```
>>> Event.objects.filter(ages__contained_by=NumericRange(0, 15))
<QuerySet [<Event: Soft play>]>
```

`contained_by` 查询也适用于非范围字段类型： [`SmallAutoField`](/zh-hans/5.2/ref/models/fields/#django.db.models.SmallAutoField), [`AutoField`](/zh-hans/5.2/ref/models/fields/#django.db.models.AutoField), [`BigAutoField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BigAutoField), [`SmallIntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.SmallIntegerField), [`IntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.IntegerField), [`BigIntegerField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BigIntegerField), [`DecimalField`](/zh-hans/5.2/ref/models/fields/#django.db.models.DecimalField), [`FloatField`](/zh-hans/5.2/ref/models/fields/#django.db.models.FloatField), [`DateField`](/zh-hans/5.2/ref/models/fields/#django.db.models.DateField), 和 [`DateTimeField`](/zh-hans/5.2/ref/models/fields/#django.db.models.DateTimeField)。例如：

```pycon
>>> from django.db.backends.postgresql.psycopg_any import DateTimeTZRange
>>> Event.objects.filter(
...     start__contained_by=DateTimeTZRange(
...         timezone.now() - datetime.timedelta(hours=1),
...         timezone.now() + datetime.timedelta(hours=1),
...     ),
... )
<QuerySet [<Event: Soft play>]>
```

##### `overlap`

```
>>> Event.objects.filter(ages__overlap=NumericRange(8, 12))
<QuerySet [<Event: Soft play>]>
```

#### 比较函数

范围字段支持标准查询：[`lt`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-lt)、[`gt`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-gt)、[`lte`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-lte) 和 [`gte`](/zh-hans/5.2/ref/models/querysets/#std-fieldlookup-gte)。这些并没有特别大的帮助——它们先比较下界，然后在必要时才比较上界。这也是用于按范围字段排序的策略。最好是使用特定的范围比较运算符。

##### `fully_lt`

返回的范围严格小于传入的范围。换句话说，返回范围内的所有点都小于传入范围内的所有点。

```
>>> Event.objects.filter(ages__fully_lt=NumericRange(11, 15))
<QuerySet [<Event: Soft play>]>
```

##### `fully_gt`

返回的范围严格大于传入的范围。换句话说，返回范围内的所有点都大于传入范围内的所有点。

```
>>> Event.objects.filter(ages__fully_gt=NumericRange(11, 15))
<QuerySet [<Event: Pub trip>]>
```

##### `not_lt`

返回的范围不包含任何小于传入范围的点，即返回范围的下界至少是传入范围的下界。

```
>>> Event.objects.filter(ages__not_lt=NumericRange(0, 15))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
```

##### `not_gt`

返回的范围不包含任何大于传入范围的点，也就是说，返回的范围的上界最多就是传入范围的上界。

```
>>> Event.objects.filter(ages__not_gt=NumericRange(3, 10))
<QuerySet [<Event: Soft play>]>
```

##### `adjacent_to`

返回的范围与传入的范围共享一个边界。

```
>>> Event.objects.filter(ages__adjacent_to=NumericRange(10, 21))
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
```

#### 使用边界进行查询

范围字段支持几个额外的查找。

##### `startswith`

返回的对象具有给定的下界。可以链入基础字段的有效查找。

```
>>> Event.objects.filter(ages__startswith=21)
<QuerySet [<Event: Pub trip>]>
```

##### `endswith`

返回的对象具有给定的上界。可以链入基础字段的有效查找。

```
>>> Event.objects.filter(ages__endswith=10)
<QuerySet [<Event: Soft play>]>
```

##### `isempty`

返回的对象是空的范围。可以链到有效的查找 [`BooleanField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BooleanField)。

```
>>> Event.objects.filter(ages__isempty=True)
<QuerySet []>
```

##### `lower_inc`

根据传递的布尔值，返回具有包含或不包含下界的对象。可以链到有效的查找 [`BooleanField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BooleanField) 的对象。

```
>>> Event.objects.filter(ages__lower_inc=True)
<QuerySet [<Event: Soft play>, <Event: Pub trip>]>
```

##### `lower_inf`

根据传递的布尔值，返回具有无界（无限）或仅有下界的对象。可以链到有效的查找 [`BooleanField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BooleanField)。

```
>>> Event.objects.filter(ages__lower_inf=True)
<QuerySet []>
```

##### `upper_inc`

根据传递的布尔值，返回具有包含或不包含上界的对象。可以链到有效的查找 [`BooleanField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BooleanField) 的对象。

```
>>> Event.objects.filter(ages__upper_inc=True)
<QuerySet []>
```

##### `upper_inf`

根据传递的布尔值，返回具有无界（无限）或仅有上界的对象。可以链到有效的查找 [`BooleanField`](/zh-hans/5.2/ref/models/fields/#django.db.models.BooleanField)。

```
>>> Event.objects.filter(ages__upper_inf=True)
<QuerySet [<Event: Pub trip>]>
```

### 定义自己的范围类型

PostgreSQL 允许定义自定义范围类型。Django 的模型和表单字段实现使用以下基类，并且 `psycopg` 提供了一个 [`register_range()`](https://www.psycopg.org/psycopg3/docs/basic/pgtypes.html#psycopg.types.range.register_range) 函数来允许使用自定义范围类型。

#### `class RangeField(**options)`

模型范围字段的基类。

#### `base_field`

要使用的模型字段类。

#### `range_type`

要使用的范围类型。

#### `form_field`

要使用的表单字段类。应该是 [`django.contrib.postgres.forms.BaseRangeField`](#django.contrib.postgres.fields.django.contrib.postgres.forms.BaseRangeField) 的子类。

#### `class django.contrib.postgres.forms.BaseRangeField`

表范围字段的基类。

#### `base_field`

要使用的表字段。

#### `range_type`

要使用的范围类型。

### 范围操作

#### `class RangeOperators`

PostgreSQL 提供了一组 SQL 运算符，这些运算符可以和范围数据类型一起使用（参见  the PostgreSQL documentation for the full details of range operators \_ ）。这个类的目的是作为一种方便的方法，以避免排版错误。运算符名称与相应的查找名称重叠。

```python
class RangeOperators:
    EQUAL = "="
    NOT_EQUAL = "<>"
    CONTAINS = "@>"
    CONTAINED_BY = "<@"
    OVERLAPS = "&&"
    FULLY_LT = "<<"
    FULLY_GT = ">>"
    NOT_LT = "&>"
    NOT_GT = "&<"
    ADJACENT_TO = "-|-"
```

### RangeBoundary() 表达式

#### `class RangeBoundary(inclusive_lower=True, inclusive_upper=False)`

#### `inclusive_lower`

如果 `True` （默认），则下界为包含 `'['`，否则为不包含 `'('`。

#### `inclusive_upper`

如果 `False` （默认），则上界为包含 `')'`，否则为不包含 `']'`。

`RangeBoundary()` 表达式表示范围边界。它可以与自定义的范围函数一起使用，预期边界，例如定义 `ExclusionConstraint`。参见 the PostgreSQL documentation for the full details \_ 。
