123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- =====================
- 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``.
|