查找 API 参考

本文档包含查找的 API 参考,即 Django 用于构建数据库查询 WHERE 子句的 API。要了解如何使用查找,请参阅 执行查询;要了解如何创建新的查找,请参阅 如何编写自定义查找

查找 API 包含两个组件:一个 RegisterLookupMixin 类,用于注册查找,以及 查询表达式 API,它是一组方法,一个类必须实现这些方法才能注册为查找。

Django 有两个遵循查询表达式 API 的基类,所有 Django 内置查找都源于这两个基类

  • Lookup:用于查找字段(例如 field_name__exactexact
  • Transform:用于转换字段

查找表达式包含三个部分

  • 字段部分(例如 Book.objects.filter(author__best_friends__first_name...);
  • 转换部分(可以省略)(例如 __lower__first3chars__reversed);
  • 查找(例如 __icontains),如果省略,则默认为 __exact

注册 API

Django 使用 RegisterLookupMixin 为类提供注册查找的接口,该接口可以作用于类本身或其实例。两个突出的例子是 Field(所有模型字段的基类)和 Transform(所有 Django 转换的基类)。

class lookups.RegisterLookupMixin

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

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 查找(可以使用 字段访问 API 来检索单个字段实例)。它会覆盖已存在且名称相同的查找。在字段实例上注册的查找优先于在类上注册的查找。如果提供了 lookup_name,则将使用它作为此查找的名称,否则将使用 lookup.lookup_name

get_lookup(lookup_name)

返回在类或类实例中注册的名为 lookup_nameLookup。默认实现会递归地查看所有父类,并检查是否有任何父类注册了名为 lookup_name 的查找,并返回第一个匹配项。实例查找会覆盖任何具有相同 lookup_name 的类查找。

get_lookups()

返回一个字典,其中包含在类或类实例中注册的每个查找名称,映射到 Lookup 类。

get_transform(transform_name)

返回在类或类实例中注册的名为 transform_nameTransform。默认实现会递归地查看所有父类,并检查是否有任何父类注册了名为 transform_name 的转换,并返回第一个匹配项。

要使一个类成为查找,它必须遵循 查询表达式 APILookupTransform 自然地遵循此 API。

在 Django 4.2 中更改

添加了对在 Field 实例上注册查找的支持。

查询表达式 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() 以了解示例用法。

as_vendorname(compiler, connection)

as_sql() 方法类似。当表达式由 compiler.compile() 编译时,Django 将首先尝试调用 as_vendorname(),其中 vendorname 是用于执行查询的后端的供应商名称。 vendorname 是 Django 内置后端的 postgresqloraclesqlitemysql 之一。

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 实例。

Transform 参考

class Transform

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

在查找表达式中使用 Transform 的表示法是 <expression>__<transformation>(例如 date__year)。

此类遵循 查询表达式 API,这意味着您可以使用 <expression>__<transform1>__<transform2>。它是一个专门的 Func() 表达式,它只接受一个参数。它也可以用在过滤器的右侧或直接用作注释。

bilateral

一个布尔值,指示此转换是否应该应用于 lhsrhs。双边转换将按它们在查找表达式中出现的顺序应用于 rhs。默认情况下,它设置为 False。有关示例用法,请参见 如何编写自定义查找

lhs

左侧 - 正在转换的内容。它必须遵循 查询表达式 API

lookup_name

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

output_field

定义此转换输出的类。它必须是 Field 实例。默认情况下与它的 lhs.output_field 相同。

Lookup 引用

class Lookup

一个 Lookup 是一个用于实现查找的通用类。查找是一个带有左侧的查询表达式,lhs;右侧,rhs;以及一个 lookup_name,用于在 lhsrhs 之间生成布尔比较,例如 lhs in rhslhs > 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。它也可以是一个普通值。

rhs

右侧 - lhs 正在与之比较的内容。它可以是一个普通值,也可以是编译成 SQL 的东西,通常是 F() 对象或 QuerySet

lookup_name

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

prepare_rhs

默认为 True。当 rhs 是一个普通值时,prepare_rhs 决定是否应该将其准备为查询中的参数。为了做到这一点,如果定义了 lhs.output_field.get_prep_value(),则调用它,否则将 rhs 包裹在 Value() 中。

process_lhs(compiler, connection, lhs=None)

返回一个元组 (lhs_string, lhs_params),如 compiler.compile(lhs) 所返回。此方法可以被重写以调整 lhs 的处理方式。

compiler 是一个 SQLCompiler 对象,用于像 compiler.compile(lhs) 一样编译 lhsconnection 可用于编译特定于供应商的 SQL。如果 lhs 不是 None,请将其用作处理后的 lhs,而不是 self.lhs

process_rhs(compiler, connection)

行为与 process_lhs() 相同,用于右侧。

返回顶部