---
title: "查找 API 参考"
version: 6.1
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/6.1/ref/models/lookups/
canonical: https://djangodocs.dev/zh-hans/6.1/ref/models/lookups/
---
# 查找 API 参考

本文档提供了查找的 API 参考，它是 Django 的 API，用于构建数据库查询的 `WHERE` 子句。要学习如何 *使用* 查找，请看 [执行查询](/zh-hans/6.1/topics/db/queries/)；要学习如何 *创建* 新的查找，请看 [如何编写自定义的查询器](/zh-hans/6.1/howto/custom-lookups/)。

查找 API 有两个组成部分：一个是 [`RegisterLookupMixin`](#django.db.models.lookups.RegisterLookupMixin) 类，用于注册查找；另一个是 [查询表达式 API](#query-expression)，一个类要想注册为查找，必须实现一组方法。

Django 有两个遵循查询表达式 API 的基类，所有 Django 内置的查找都是从这里派生出来的。

- [`Lookup`](#django.db.models.Lookup)：查找一个字段（例如 `field_name__exact` 的 `exact`）
- [`Transform`](#django.db.models.Transform)：转换一个字段

一个查找表达式由三部分组成：

- Fields part, e.g.
  `Book.objects.filter(author__best_friends__first_name...`);
- 转换部分（可省略）（如 `__lower__first3chars__reversed`）；
- 查找（例如 `__icontains`），如果省略，默认为 `__exact`。

## 注册 API

Django 使用 [`RegisterLookupMixin`](#django.db.models.lookups.RegisterLookupMixin) 为一个类提供了在其自身或其实例上注册查找的接口。两个显著的例子是 [`Field`](/zh-hans/6.1/ref/models/fields/#django.db.models.Field)，所有模型字段的基类，以及 [`Transform`](#django.db.models.Transform)，所有 Django 转换的基类。

#### `class lookups.RegisterLookupMixin`

一个在类上实现查找 API 的混入。

#### `classmethod register_lookup(lookup, lookup_name=None)`

在类或类实例中注册一个新的查找。例如：

```
DateField.register_lookup(YearExact)
User._meta.get_field("date_joined").register_lookup(MonthExact)
```

将在 `DateField` 上注册 `YearExact` 查找，以及在 `User.date_joined` 上注册 `MonthExact` 查找（您可以使用 [Field Access API](/zh-hans/6.1/ref/models/meta/#model-meta-field-api) 来检索单个字段实例）。它会覆盖同名的已经存在的查找。在字段实例上注册的查找优先于在类上注册的查找。如果提供了 `lookup_name`，将用于此查找，否则将使用 `lookup.lookup_name`。

#### `get_lookup(lookup_name)`

返回在调用它的类或类实例中注册的名为 `lookup_name` 的 [`Lookup`](#django.db.models.Lookup)。默认实现递归地查找所有父类，并检查是否有任何一个父类注册了名为 `lookup_name` 的查找，返回第一个匹配项。实例上的查找将覆盖具有相同 `lookup_name` 的任何类上的查找。

#### `get_lookups()`

返回一个字典，其中包含在类或类实例中注册的每个查找名称，以及与之对应的 [`Lookup`](#django.db.models.Lookup) 类。

#### `get_transform(transform_name)`

返回在类或类实例中注册的名为 `transform_name` 的 [`Transform`](#django.db.models.Transform)。默认实现递归地查找所有父类，检查是否有任何一个父类注册了名为 `transform_name` 的转换，返回第一个匹配项。

一个类要想成为查找，必须遵循 [查询表达式 API](#query-expression)。 [`Lookup`](#django.db.models.Lookup) 和 [`Transform`](#django.db.models.Transform) 自然遵循这个API。

## 查询表达式 API

查询表达式 API 是一组通用的方法，这些方法被定义为可用于查询表达式，将自己翻译成 SQL 表达式。直接字段引用、聚合和 `Transform` 是遵循这个 API 的例子。当一个类实现了以下方法时，就可以说它遵循了查询表达式 API：

#### `as_sql(compiler, connection)`

生成表达式的 SQL 片段。返回一个元组 `(sql, params)`，其中 `sql` 是 SQL 字符串，`params` 是查询参数的列表或元组。`compiler` 是一个 `SQLCompiler` 对象，它有一个 `compile()` 方法，可以用来编译其他表达式。`connection` 是用于执行查询的连接。

调用 `expression.as_sql()` 通常是不正确的，应该使用 `compiler.compile(expression)`。`compiler.compile()` 方法将负责调用特定厂商的表达式方法。

如果 `as_vendorname()` 方法或子类很可能需要提供数据来覆盖 SQL 字符串的生成，可以在这个方法上定义自定义关键字参数。参见 [`Func.as_sql()`](/zh-hans/6.1/ref/models/expressions/#django.db.models.Func.as_sql) 的用法示例。

#### `as_vendorname(compiler, connection)`

和 `as_sql()` 方法一样工作。当一个表达式被 `compiler.compile()` 编译后，Django 会先尝试调用 `as_vendorname()`，其中 `vendorname` 是执行查询的后端厂商名称。`vendorname` 是 Django 内置后端的 `postgresql`、`oracle`、`sqlite`、`mysql` 中的一个。

#### `get_lookup(lookup_name)`

必须返回名为 `lookup_name` 的查找。例如，返回 `self.output_field.get_lookup(lookup_name)`。

#### `get_transform(transform_name)`

必须返回名为 `transform_name` 的查找。例如，返回 `self.output_field.get_transform(transform_name)`。

#### `output_field`

定义 `get_lookup()` 方法返回的类的类型。它必须是一个 [`Field`](/zh-hans/6.1/ref/models/fields/#django.db.models.Field) 实例。

## `Transform` 参考

#### `class Transform`

`Transform` 是一个实现字段转换的通用类。一个突出的例子是 `__year`，它将 `DateField` 转变为 `IntegerField`。

在查询表达式中使用 `Transform` 的符号是 `<expression>__<transformation>` （例如 `date__year`）。

This class follows the [Query Expression API](#query-expression),
which implies that you can use
`<expression>__<transform1>__<transform2>`. It's a specialized
[Func() expression](/zh-hans/6.1/ref/models/expressions/#func-expressions) that only accepts one argument.
It can also be used on the right hand side of a filter or directly as an
annotation.

#### `bilateral`

一个布尔值，表示这一转换是否应适用于 `lhs` 和 `rhs`。双边转换将按照查找表达式中出现的顺序应用于 `rhs`。默认情况下，它被设置为 `False`。关于用法示例，请参见 [如何编写自定义的查询器](/zh-hans/6.1/howto/custom-lookups/)。

#### `lhs`

左侧——正在转换的内容。它必须遵循 [查询表达式 API](#query-expression)。

#### `lookup_name`

查找的名称，用于在解析查询表达式时识别它。它不能包含字符串 `"__"`。

#### `output_field`

定义这个转换输出的类。它必须是一个 [`Field`](/zh-hans/6.1/ref/models/fields/#django.db.models.Field) 实例。默认情况下是与其 `lhs.output_field` 相同。

## `Lookup` 参考

#### `class Lookup`

`Lookup` 是一个实现查找的通用类。一个查找是一个查询表达式，它的左侧是 [`lhs`](#django.db.models.Lookup.lhs)；右侧是 [`rhs`](#django.db.models.Lookup.rhs)；还有一个 `lookup_name`，用于在 `lhs` 和 `rhs` 之间进行布尔比较，例如 `lhs in rhs` 或 `lhs > rhs`。

在表达式中使用查找的主要符号是 `<lhs>__<lookup_name>=<rhs>`。查询也可以直接在 `QuerySet` 过滤器中使用：

```
Book.objects.filter(LessThan(F("word_count"), 7500))
```

...或注解：

```
Book.objects.annotate(is_short_story=LessThan(F("word_count"), 7500))
```

#### `lhs`

左手边——被查询的内容。该对象通常遵循 [查询表达式 API](#query-expression)。它也可以是一个普通的值。

#### `rhs`

右侧——`lhs` 与什么进行比较。它可以是一个普通的值，也可以是编译成 SQL 的东西，通常是一个 `F()` 对象或一个 `QuerySet`。

#### `lookup_name`

这个查询的名称，用于在解析查询表达式时识别它。它不能包含字符串 `"__"`。

#### `prepare_rhs`

默认为 `True`。当 [`rhs`](#django.db.models.Lookup.rhs) 是一个普通值时，[`prepare_rhs`](#django.db.models.Lookup.prepare_rhs) 决定是否应该准备它以在查询中作为参数使用。为了实现这一点，如果定义了 `lhs.output_field.get_prep_value()`，则会调用它，否则将 [`rhs`](#django.db.models.Lookup.rhs) 包装在 [`Value()`](/zh-hans/6.1/ref/models/expressions/#django.db.models.Value) 中。

#### `process_lhs(compiler, connection, lhs=None)`

返回由 `compiler.compile(lhs)` 返回的元组 `(lhs_string, lhs_params)`。这个方法可以被重写来调整 `lhs` 的处理方式。

`compiler` 是一个 `SQLCompiler` 对象，可以像 `compiler.compile(lhs)` 一样用来编译 `lhs`。`connection` 可以用于编译厂商特定的 SQL。如果 `lhs` 不是 `None`，就用它作为处理后的 `lhs` 代替 `self.lhs`。

#### `process_rhs(compiler, connection)`

右侧的行为与 [`process_lhs()`](#django.db.models.Lookup.process_lhs) 相同。
