diff options
Diffstat (limited to 'docs/ref/models/lookups.txt')
| -rw-r--r-- | docs/ref/models/lookups.txt | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/docs/ref/models/lookups.txt b/docs/ref/models/lookups.txt new file mode 100644 index 0000000000..ef331aa0ab --- /dev/null +++ b/docs/ref/models/lookups.txt @@ -0,0 +1,207 @@ +==================== +Lookup API reference +==================== + +.. module:: django.db.models.lookups + :synopsis: Lookups API + +.. currentmodule:: django.db.models + +.. versionadded:: 1.7 + +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 +:doc:`/topics/db/queries`; to learn how to *create* new lookups, see +:doc:`/howto/custom-lookups`. + +The lookup API has two components: a :class:`~lookups.RegisterLookupMixin` class +that registers lookups, and the `Query Expression API <query-expression>`_, 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: + +* :class:`Lookup`: to lookup a field (e.g. the ``exact`` of ``field_name__exact``) +* :class:`Transform`: to transform a field + +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``. + +.. _lookup-registration-api: + +Registration API +~~~~~~~~~~~~~~~~ + +Django uses :class:`~lookups.RegisterLookupMixin` to give a class the interface to +register lookups on itself. The two prominent examples are +:class:`~django.db.models.Field`, the base class of all model fields, and +``Aggregate``, the base class of all Django aggregates. + +.. class:: lookups.RegisterLookupMixin + + A mixin that implements the lookup API on a class. + + .. classmethod:: register_lookup(lookup) + + Registers a new lookup in the class. For example + ``DateField.register_lookup(YearExact)`` will register ``YearExact`` + lookup on ``DateField``. It overrides a lookup that already exists with + the same name. + + .. method:: get_lookup(lookup_name) + + Returns the :class:`Lookup` named ``lookup_name`` registered in the class. + The default implementation looks recursively on all parent classes + and checks if any has a registered lookup named ``lookup_name``, returning + the first match. + + .. method:: get_transform(transform_name) + + Returns a :class:`Transform` named ``transform_name``. The default + implementation looks recursively on all parent classes to check if any + has the registered transform named ``transform_name``, returning the first + match. + +For a class to be a lookup, it must follow the `Query Expression API +<query-expression>`_. :class:`~Lookup` and :class:`~Transform` naturally +follow this API. + +.. _query-expression: + +The Query Expression API +~~~~~~~~~~~~~~~~~~~~~~~~ + +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: + +.. method:: as_sql(self, qn, connection) + + Responsible for producing the query string and parameters for the expression. + The ``qn`` 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 + ``qn.compile(expression)`` should be used. The ``qn.compile()`` method will + take care of calling vendor-specific methods of the expression. + +.. method:: as_vendorname(self, qn, connection) + + Works like ``as_sql()`` method. When an expression is compiled by + ``qn.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. + +.. method:: get_lookup(lookup_name) + + Must return the lookup named ``lookup_name``. For instance, by returning + ``self.output_field.get_lookup(lookup_name)``. + +.. method:: get_transform(transform_name) + + Must return the lookup named ``transform_name``. For instance, by returning + ``self.output_field.get_transform(transform_name)``. + +.. attribute:: output_field + + Defines the type of class returned by the ``get_lookup()`` method. It must + be a :class:`~django.db.models.Field` instance. + +Transform reference +~~~~~~~~~~~~~~~~~~~ + +.. class:: Transform + + 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 an lookup expression is + ``<expression>__<transformation>`` (e.g. ``date__year``). + + This class follows the `Query Expression API <query-expression>`_, which + implies that you can use ``<expression>__<transform1>__<transform2>``. + + .. attribute:: lhs + + The left-hand side - what is being transformed. It must follow the + `Query Expression API <query-expression>`_. + + .. attribute:: lookup_name + + The name of the lookup, used for identifying it on parsing query + expressions. It cannot contain the string ``"__"``. + + .. attribute:: output_field + + Defines the class this transformation outputs. It must be a + :class:`~django.db.models.Field` instance. By default is the same as + its ``lhs.output_field``. + + .. method:: as_sql + + To be overridden; raises :exc:`NotImplementedError`. + + .. method:: get_lookup(lookup_name) + + Same as :meth:`~lookups.RegisterLookupMixin.get_lookup()`. + + .. method:: get_transform(transform_name) + + Same as :meth:`~lookups.RegisterLookupMixin.get_transform()`. + +Lookup reference +~~~~~~~~~~~~~~~~ + +.. class:: Lookup + + A ``Lookup`` is a generic class to implement lookups. A lookup is a query + expression with a left-hand side, :attr:`lhs`; a right-hand side, + :attr:`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 notation to use a lookup in an expression is + ``<lhs>__<lookup_name>=<rhs>``. + + This class doesn't follow the `Query Expression API <query-expression>`_ + since it has ``=<rhs>`` on its construction: lookups are always the end of + a lookup expression. + + .. attribute:: lhs + + The left-hand side - what is being looked up. The object must follow + the `Query Expression API <query-expression>`_. + + .. attribute:: rhs + + 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``. + + .. attribute:: lookup_name + + The name of this lookup, used to identify it on parsing query + expressions. It cannot contain the string ``"__"``. + + .. method:: process_lhs(qn, connection[, lhs=None]) + + Returns a tuple ``(lhs_string, lhs_params)``, as returned by + ``qn.compile(lhs)``. This method can be overridden to tune how the + ``lhs`` is processed. + + ``qn`` is an ``SQLCompiler`` object, to be used like ``qn.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``. + + .. method:: process_rhs(qn, connection) + + Behaves the same way as :meth:`process_lhs`, for the right-hand side. |
