mirror of
https://github.com/django/django.git
synced 2024-11-18 15:34:16 +00:00
161 lines
6.0 KiB
Plaintext
161 lines
6.0 KiB
Plaintext
=====================
|
|
Query-related classes
|
|
=====================
|
|
|
|
.. currentmodule:: django.db.models
|
|
|
|
This document provides reference material for query-related tools not
|
|
documented elsewhere.
|
|
|
|
``F()`` expressions
|
|
===================
|
|
|
|
.. class:: F
|
|
|
|
An ``F()`` object represents the value of a model field. It makes it possible
|
|
to refer to model field values and perform database operations using them
|
|
without actually having to pull them out of the database into Python memory.
|
|
|
|
Instead, Django uses the ``F()`` object to generate a SQL expression that
|
|
describes the required operation at the database level.
|
|
|
|
This is easiest to understand through an example. Normally, one might do
|
|
something like this::
|
|
|
|
# Tintin filed a news story!
|
|
reporter = Reporters.objects.get(name='Tintin')
|
|
reporter.stories_filed += 1
|
|
reporter.save()
|
|
|
|
Here, we have pulled the value of ``reporter.stories_filed`` from the database
|
|
into memory and manipulated it using familiar Python operators, and then saved
|
|
the object back to the database. But instead we could also have done::
|
|
|
|
from django.db.models import F
|
|
reporter = Reporters.objects.get(name='Tintin')
|
|
reporter.stories_filed = F('stories_filed') + 1
|
|
reporter.save()
|
|
|
|
Although ``reporter.stories_filed = F('stories_filed') + 1`` looks like a
|
|
normal Python assignment of value to an instance attribute, in fact it's an SQL
|
|
construct describing an operation on the database.
|
|
|
|
When Django encounters an instance of ``F()``, it overrides the standard Python
|
|
operators to create an encapsulated SQL expression; in this case, one which
|
|
instructs the database to increment the database field represented by
|
|
``reporter.stories_filed``.
|
|
|
|
Whatever value is or was on ``reporter.stories_filed``, Python never gets to
|
|
know about it - it is dealt with entirely by the database. All Python does,
|
|
through Django's ``F()`` class, is create the SQL syntax to refer to the field
|
|
and describe the operation.
|
|
|
|
.. note::
|
|
|
|
In order to access the new value that has been saved in this way, the object
|
|
will need to be reloaded::
|
|
|
|
reporter = Reporters.objects.get(pk=reporter.pk)
|
|
|
|
As well as being used in operations on single instances as above, ``F()`` can
|
|
be used on ``QuerySets`` of object instances, with ``update()``. This reduces
|
|
the two queries we were using above - the ``get()`` and the
|
|
:meth:`~Model.save()` - to just one::
|
|
|
|
reporter = Reporters.objects.filter(name='Tintin')
|
|
reporter.update(stories_filed=F('stories_filed') + 1)
|
|
|
|
We can also use :meth:`~django.db.models.query.QuerySet.update()` to increment
|
|
the field value on multiple objects - which could be very much faster than
|
|
pulling them all into Python from the database, looping over them, incrementing
|
|
the field value of each one, and saving each one back to the database::
|
|
|
|
Reporter.objects.all().update(stories_filed=F('stories_filed') + 1)
|
|
|
|
``F()`` therefore can offer performance advantages by:
|
|
|
|
* getting the database, rather than Python, to do work
|
|
* reducing the number of queries some operations require
|
|
|
|
.. _avoiding-race-conditions-using-f:
|
|
|
|
Avoiding race conditions using ``F()``
|
|
--------------------------------------
|
|
|
|
Another useful benefit of ``F()`` is that having the database - rather than
|
|
Python - update a field's value avoids a *race condition*.
|
|
|
|
If two Python threads execute the code in the first example above, one thread
|
|
could retrieve, increment, and save a field's value after the other has
|
|
retrieved it from the database. The value that the second thread saves will be
|
|
based on the original value; the work of the first thread will simply be lost.
|
|
|
|
If the database is responsible for updating the field, the process is more
|
|
robust: it will only ever update the field based on the value of the field in
|
|
the database when the :meth:`~Model.save()` or ``update()`` is executed, rather
|
|
than based on its value when the instance was retrieved.
|
|
|
|
Using ``F()`` in filters
|
|
------------------------
|
|
|
|
``F()`` is also very useful in ``QuerySet`` filters, where they make it
|
|
possible to filter a set of objects against criteria based on their field
|
|
values, rather than on Python values.
|
|
|
|
This is documented in :ref:`using F() expressions in queries
|
|
<using-f-expressions-in-filters>`
|
|
|
|
Supported operations with ``F()``
|
|
---------------------------------
|
|
|
|
As well as addition, Django supports subtraction, multiplication, division,
|
|
and modulo arithmetic with ``F()`` objects, using Python constants,
|
|
variables, and even other ``F()`` objects.
|
|
|
|
.. versionadded:: 1.7
|
|
|
|
The power operator ``**`` is also supported.
|
|
|
|
``Q()`` objects
|
|
===============
|
|
|
|
.. class:: Q
|
|
|
|
A ``Q()`` object, like an :class:`~django.db.models.F` object, encapsulates a
|
|
SQL expression in a Python object that can be used in database-related
|
|
operations.
|
|
|
|
In general, ``Q() objects`` make it possible to define and reuse conditions.
|
|
This permits the :ref:`construction of complex database queries
|
|
<complex-lookups-with-q>` using ``|`` (``OR``) and ``&`` (``AND``) operators;
|
|
in particular, it is not otherwise possible to use ``OR`` in ``QuerySets``.
|
|
|
|
``Prefetch()`` objects
|
|
======================
|
|
|
|
.. versionadded:: 1.7
|
|
|
|
.. class:: Prefetch(lookup, queryset=None, to_attr=None)
|
|
|
|
The ``Prefetch()`` object can be used to control the operation of
|
|
:meth:`~django.db.models.query.QuerySet.prefetch_related()`.
|
|
|
|
The ``lookup`` argument describes the relations to follow and works the same
|
|
as the string based lookups passed to
|
|
:meth:`~django.db.models.query.QuerySet.prefetch_related()`.
|
|
|
|
The ``queryset`` argument supplies a base ``QuerySet`` for the given lookup.
|
|
This is useful to further filter down the prefetch operation, or to call
|
|
:meth:`~django.db.models.query.QuerySet.select_related()` from the prefetched
|
|
relation, hence reducing the number of queries even further.
|
|
|
|
The ``to_attr`` argument sets the result of the prefetch operation to a custom
|
|
attribute.
|
|
|
|
.. note::
|
|
|
|
When using ``to_attr`` the prefetched result is stored in a list.
|
|
This can provide a significant speed improvement over traditional
|
|
``prefetch_related`` calls which store the cached result within a
|
|
``QuerySet`` instance.
|