This document has the API references of lookups, the Django API for building
the WHERE
clause of a database query. To learn how to use lookups, see
Making queries; to learn how to create new lookups, see
How to write custom lookups.
The lookup API has two components: a RegisterLookupMixin
class
that registers lookups, and the Query Expression API, a
set of methods that a class has to implement to be registrable as a lookup.
Django has two base classes that follow the query expression API and from where all Django builtin lookups are derived:
A lookup expression consists of three parts:
Fields part (e.g. Book.objects.filter(author__best_friends__first_name...
);
Transforms part (may be omitted) (e.g. __lower__first3chars__reversed
);
A lookup (e.g. __icontains
) that, if omitted, defaults to __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.
A mixin that implements the lookup API on a class.
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.
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
.
For a class to be a lookup, it must follow the Query Expression API. Lookup
and Transform
naturally
follow this API.
Support for registering lookups on Field
instances was added.
The query expression API is a common set of methods that classes define to be
usable in query expressions to translate themselves into SQL expressions. Direct
field references, aggregates, and Transform
are examples that follow this
API. A class is said to follow the query expression API when it implements the
following methods:
Generates the SQL fragment for the expression. Returns a tuple
(sql, params)
, where sql
is the SQL string, and params
is the
list or tuple of query parameters. The compiler
is an SQLCompiler
object, which has a compile()
method that can be used to compile other
expressions. The connection
is the connection used to execute the
query.
Calling expression.as_sql()
is usually incorrect - instead
compiler.compile(expression)
should be used. The compiler.compile()
method will take care of calling vendor-specific methods of the expression.
Custom keyword arguments may be defined on this method if it’s likely that
as_vendorname()
methods or subclasses will need to supply data to
override the generation of the SQL string. See Func.as_sql()
for
example usage.
Works like as_sql()
method. When an expression is compiled by
compiler.compile()
, Django will first try to call as_vendorname()
,
where vendorname
is the vendor name of the backend used for executing
the query. The vendorname
is one of postgresql
, oracle
,
sqlite
, or mysql
for Django’s built-in backends.
Must return the lookup named lookup_name
. For instance, by returning
self.output_field.get_lookup(lookup_name)
.
Must return the lookup named transform_name
. For instance, by returning
self.output_field.get_transform(transform_name)
.
Transform
reference¶A Transform
is a generic class to implement field transformations. A
prominent example is __year
that transforms a DateField
into a
IntegerField
.
The notation to use a Transform
in a lookup expression is
<expression>__<transformation>
(e.g. date__year
).
This class follows the Query Expression API, which
implies that you can use <expression>__<transform1>__<transform2>
. It’s
a specialized Func() expression that only accepts
one argument. It can also be used on the right hand side of a filter or
directly as an annotation.
A boolean indicating whether this transformation should apply to both
lhs
and rhs
. Bilateral transformations will be applied to rhs
in
the same order as they appear in the lookup expression. By default it is set
to False
. For example usage, see How to write custom lookups.
The left-hand side - what is being transformed. It must follow the Query Expression API.
The name of the lookup, used for identifying it on parsing query
expressions. It cannot contain the string "__"
.
Lookup
reference¶A Lookup
is a generic class to implement lookups. A lookup is a query
expression with a left-hand side, lhs
; a right-hand side,
rhs
; and a lookup_name
that is used to produce a boolean
comparison between lhs
and rhs
such as lhs in rhs
or
lhs > rhs
.
The primary notation to use a lookup in an expression is
<lhs>__<lookup_name>=<rhs>
. Lookups can also be used directly in
QuerySet
filters:
Book.objects.filter(LessThan(F("word_count"), 7500))
…or annotations:
Book.objects.annotate(is_short_story=LessThan(F("word_count"), 7500))
The left-hand side - what is being looked up. The object typically follows the Query Expression API. It may also be a plain value.
The right-hand side - what lhs
is being compared against. It can be
a plain value, or something that compiles into SQL, typically an
F()
object or a QuerySet
.
The name of this lookup, used to identify it on parsing query
expressions. It cannot contain the string "__"
.
Returns a tuple (lhs_string, lhs_params)
, as returned by
compiler.compile(lhs)
. This method can be overridden to tune how
the lhs
is processed.
compiler
is an SQLCompiler
object, to be used like
compiler.compile(lhs)
for compiling lhs
. The connection
can be used for compiling vendor specific SQL. If lhs
is not
None
, use it as the processed lhs
instead of self.lhs
.
Behaves the same way as process_lhs()
, for the right-hand side.
Dec 25, 2023