本文档提供了查找的 API 参考,它是 Django 的 API,用于构建数据库查询的 WHERE
子句。要学习如何 使用 查找,请看 执行查询;要学习如何 创建 新的查找,请看 如何编写自定义的查询器。
查找 API 有两个组成部分:一个是 RegisterLookupMixin
类,用于注册查找;另一个是 查询表达式 API,一个类要想注册为查找,必须实现一组方法。
Django 有两个遵循查询表达式 API 的基类,所有 Django 内置的查找都是从这里派生出来的。
一个查找表达式由三部分组成:
Book.objects.filter(author__best_friends__first_name...
);__lower__first3chars__reversed
);__icontains
),如果省略,默认为 __exact
。Django uses RegisterLookupMixin
to give a class the interface to
register lookups on itself or its instances. The two prominent examples are
Field
, the base class of all model fields, and
Transform
, the base class of all Django transforms.
lookups.
RegisterLookupMixin
¶一个在类上实现查找 API 的混入。
register_lookup
(lookup, lookup_name=None)¶Registers a new lookup in the class or class instance. For example:
DateField.register_lookup(YearExact)
User._meta.get_field("date_joined").register_lookup(MonthExact)
will register YearExact
lookup on DateField
and MonthExact
lookup on the User.date_joined
(you can use Field Access API to retrieve a single field instance). It
overrides a lookup that already exists with the same name. Lookups
registered on field instances take precedence over the lookups
registered on classes. lookup_name
will be used for this lookup if
provided, otherwise lookup.lookup_name
will be used.
get_lookup
(lookup_name)¶Returns the Lookup
named lookup_name
registered in the
class or class instance depending on what calls it. The default
implementation looks recursively on all parent classes and checks if
any has a registered lookup named lookup_name
, returning the first
match. Instance lookups would override any class lookups with the same
lookup_name
.
一个类要想成为查找,必须遵循 查询表达式 API。 Lookup
和 Transform
自然遵循这个API。
Support for registering lookups on Field
instances was added.
查询表达式 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 内置后端的 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)
。
Transform
参考¶Transform
¶Transform
是一个实现字段转换的通用类。一个突出的例子是 __year
,它将 DateField
转变为 IntegerField
。
在查询表达式中使用 Transform
的符号是 <expression>__<transformation>
(例如 date__year
)。
这个类遵循 查询表达式 API,这意味着你可以使用 <expression>__<transform1>__<transform2>
。它是一个专门的 Func() 表达式,只接受一个参数。 它也可以用在过滤器的右侧,或者直接作为注解使用。
bilateral
¶一个布尔值,表示这一转换是否应适用于 lhs
和 rhs
。双边转换将按照查找表达式中出现的顺序应用于 rhs
。默认情况下,它被设置为 False
。关于用法示例,请参见 如何编写自定义的查询器。
lookup_name
¶查找的名称,用于在解析查询表达式时识别它。它不能包含字符串 "__"
。
Lookup
参考¶Lookup
¶Lookup
是一个实现查找的通用类。一个查找是一个查询表达式,它的左侧是 lhs
;右侧是 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))
rhs
¶右侧——lhs
与什么进行比较。它可以是一个普通的值,也可以是编译成 SQL 的东西,通常是一个 F()
对象或一个 QuerySet
。
lookup_name
¶这个查询的名称,用于在解析查询表达式时识别它。它不能包含字符串 "__"
。
prepare_rhs
¶Defaults to True
. When rhs
is a plain value,
prepare_rhs
determines whether it should be prepared for use as
a parameter in a query. In order to do so,
lhs.output_field.get_prep_value()
is called if defined, or rhs
is wrapped in Value()
otherwise.
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()
相同。
12月 05, 2023