mirror of
https://github.com/django/django.git
synced 2024-11-29 14:46:18 +01:00
128 lines
4.9 KiB
Plaintext
128 lines
4.9 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 though 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.
|
||
|
|
||
|
``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``.
|