Commit e8cd65f8 authored by Tim Graham's avatar Tim Graham
Browse files

Fixed #25213 -- Discouraged use of QuerySet.extra()

Thanks Anssi Kääriäinen for the draft text and Simon Charette
for review.
parent 97fa7fe9
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -1120,6 +1120,34 @@ Sometimes, the Django query syntax by itself can't easily express a complex
``QuerySet`` modifier — a hook for injecting specific clauses into the SQL
generated by a ``QuerySet``.

.. admonition:: Use this method as a last resort

    This is an old API that we aim to deprecate at some point in the future.
    Use it only if you cannot express your query using other queryset methods.
    If you do need to use it, please `file a ticket
    <https://code.djangoproject.com/newticket>`_ using the `QuerySet.extra
    keyword <https://code.djangoproject.com/query?status=assigned&status=new&keywords=~QuerySet.extra>`_
    with your use case (please check the list of existing tickets first) so
    that we can enhance the QuerySet API to allow removing ``extra()``. We are
    no longer improving or fixing bugs for this method.

    For example, this use of ``extra()``::

        >>> qs.extra(
        ...     select={'val': "select col from sometable where othercol = %s"},
        ...     select_params=(someparam,),
        ... )

    is equivalent to::

        >>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

    The main benefit of using :class:`~django.db.models.expressions.RawSQL` is
    that you can set ``output_field`` if needed. The main downside is that if
    you refer to some table alias of the queryset in the raw SQL, then it is
    possible that Django might change that alias (for example, when the
    queryset is used as a subquery in yet another query).

.. warning::

    You should be very careful whenever you use ``extra()``. Every time you use
+5 −5
Original line number Diff line number Diff line
@@ -130,12 +130,12 @@ For instance:

If these aren't enough to generate the SQL you need:

Use ``QuerySet.extra()``
------------------------
Use ``RawSQL``
--------------

A less portable but more powerful method is
:meth:`~django.db.models.query.QuerySet.extra()`, which allows some SQL to be
explicitly added to the query. If that still isn't powerful enough:
A less portable but more powerful method is the
:class:`~django.db.models.expressions.RawSQL` expression, which allows some SQL
to be explicitly added to the query. If that still isn't powerful enough:

Use raw SQL
-----------