|
@@ -0,0 +1,127 @@
|
|
|
+=====================
|
|
|
+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``.
|