File: queries.txt

package info (click to toggle)
python-django 1.7.11-1%2Bdeb8u3
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 45,624 kB
  • sloc: python: 171,189; xml: 713; sh: 203; makefile: 199; sql: 11
file content (160 lines) | stat: -rw-r--r-- 6,139 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
=====================
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.