Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge pull request #1544 from evildmp/ticket_20920_rebase

Fixed #20920 -- Consolidated F() and Q() documentation
  • Loading branch information...
commit 263eecc583223652dd24f9189144b39d5dd5b62d 2 parents 05e14e8 + 79cc666
Daniele Procida authored September 06, 2013
3  docs/index.txt
@@ -65,7 +65,8 @@ manipulating the data of your Web application. Learn more about it below:
65 65
 
66 66
 * **QuerySets:**
67 67
   :doc:`Executing queries <topics/db/queries>` |
68  
-  :doc:`QuerySet method reference <ref/models/querysets>`
  68
+  :doc:`QuerySet method reference <ref/models/querysets>` |
  69
+  :doc:`Query-related classes <ref/models/queries>`
69 70
 
70 71
 * **Model instances:**
71 72
   :doc:`Instance methods <ref/models/instances>` |
11  docs/ref/models/fields.txt
@@ -1062,11 +1062,12 @@ define the details of how the relation works.
1062 1062
     only allows the choice of related objects with a ``pub_date`` before the
1063 1063
     current date to be chosen.
1064 1064
 
1065  
-    Instead of a dictionary this can also be a :class:`~django.db.models.Q`
1066  
-    object for more :ref:`complex queries <complex-lookups-with-q>`. However,
1067  
-    if ``limit_choices_to`` is a :class:`~django.db.models.Q` object then it
1068  
-    will only have an effect on the choices available in the admin when the
1069  
-    field is not listed in ``raw_id_fields`` in the ``ModelAdmin`` for the model.
  1065
+    Instead of a dictionary this can also be a :class:`Q object
  1066
+    <django.db.models.Q>` for more :ref:`complex queries
  1067
+    <complex-lookups-with-q>`. However, if ``limit_choices_to`` is a :class:`Q
  1068
+    object <django.db.models.Q>` then it will only have an effect on the
  1069
+    choices available in the admin when the field is not listed in
  1070
+    ``raw_id_fields`` in the ``ModelAdmin`` for the model.
1070 1071
 
1071 1072
 .. attribute:: ForeignKey.related_name
1072 1073
 
1  docs/ref/models/index.txt
@@ -12,3 +12,4 @@ Model API reference. For introductory material, see :doc:`/topics/db/models`.
12 12
    options
13 13
    instances
14 14
    querysets
  15
+   queries
34  docs/ref/models/instances.txt
@@ -342,6 +342,8 @@ only.
342 342
 
343 343
 Using ``update_fields`` will force an update similarly to ``force_update``.
344 344
 
  345
+.. _ref-models-field-updates-using-f-expressions:
  346
+
345 347
 Updating attributes based on existing fields
346 348
 --------------------------------------------
347 349
 
@@ -356,35 +358,21 @@ achieve this is to do something like::
356 358
 If the old ``number_sold`` value retrieved from the database was 10, then
357 359
 the value of 11 will be written back to the database.
358 360
 
359  
-This sequence has a standard update problem in that it contains a race
360  
-condition. If another thread of execution has already saved an updated value
361  
-after the current thread retrieved the old value, the current thread will only
362  
-save the old value plus one, rather than the new (current) value plus one.
363  
-
364  
-The process can be made robust and slightly faster by expressing the update
365  
-relative to the original field value, rather than as an explicit assignment of
366  
-a new value. Django provides :ref:`F() expressions <query-expressions>` for
367  
-performing this kind of relative update. Using ``F()`` expressions, the
368  
-previous example is expressed as::
  361
+The process can be made robust, :ref:`avoiding a race condition
  362
+<avoiding-race-conditions-using-f>`, as well as slightly faster by expressing
  363
+the update relative to the original field value, rather than as an explicit
  364
+assignment of a new value. Django provides :class:`F expressions
  365
+<django.db.models.F>` for performing this kind of relative update. Using
  366
+:class:`F expressions <django.db.models.F>`, the previous example is expressed
  367
+as::
369 368
 
370 369
     >>> from django.db.models import F
371 370
     >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
372 371
     >>> product.number_sold = F('number_sold') + 1
373 372
     >>> product.save()
374 373
 
375  
-This approach doesn't use the initial value from the database. Instead, it
376  
-makes the database do the update based on whatever value is current at the time
377  
-that the :meth:`~Model.save()` is executed.
378  
-
379  
-Once the object has been saved, you must reload the object in order to access
380  
-the actual value that was applied to the updated field::
381  
-
382  
-    >>> product = Products.objects.get(pk=product.pk)
383  
-    >>> print(product.number_sold)
384  
-    42
385  
-
386  
-For more details, see the documentation on :ref:`F() expressions
387  
-<query-expressions>` and their :ref:`use in update queries
  374
+For more details, see the documentation on :class:`F expressions
  375
+<django.db.models.F>` and their :ref:`use in update queries
388 376
 <topics-db-queries-update>`.
389 377
 
390 378
 Specifying which fields to save
127  docs/ref/models/queries.txt
... ...
@@ -0,0 +1,127 @@
  1
+=====================
  2
+Query-related classes
  3
+=====================
  4
+
  5
+.. currentmodule:: django.db.models
  6
+
  7
+This document provides reference material for query-related tools not
  8
+documented elsewhere.
  9
+
  10
+``F()`` expressions
  11
+===================
  12
+
  13
+.. class:: F
  14
+
  15
+An ``F()`` object represents the value of a model field. It makes it possible
  16
+to refer to model field values and perform database operations using them
  17
+without actually having to pull them out of the database into Python memory.
  18
+
  19
+Instead, Django uses the ``F()`` object to generate a SQL expression that
  20
+describes the required operation at the database level.
  21
+
  22
+This is easiest to understand though an example. Normally, one might do
  23
+something like this::
  24
+
  25
+    # Tintin filed a news story!
  26
+    reporter = Reporters.objects.get(name='Tintin')
  27
+    reporter.stories_filed += 1
  28
+    reporter.save()
  29
+
  30
+Here, we have pulled the value of ``reporter.stories_filed`` from the database
  31
+into memory and manipulated it using familiar Python operators, and then saved
  32
+the object back to the database. But instead we could also have done::
  33
+
  34
+    from django.db.models import F
  35
+    reporter = Reporters.objects.get(name='Tintin')
  36
+    reporter.stories_filed = F('stories_filed') + 1
  37
+    reporter.save()
  38
+
  39
+Although ``reporter.stories_filed = F('stories_filed') + 1`` looks like a
  40
+normal Python assignment of value to an instance attribute, in fact it's an SQL
  41
+construct describing an operation on the database.
  42
+
  43
+When Django encounters an instance of ``F()``, it overrides the standard Python
  44
+operators to create an encapsulated SQL expression; in this case, one which
  45
+instructs the database to increment the database field represented by
  46
+``reporter.stories_filed``.
  47
+
  48
+Whatever value is or was on ``reporter.stories_filed``, Python never gets to
  49
+know about it - it is dealt with entirely by the database. All Python does,
  50
+through Django's ``F()`` class, is create the SQL syntax to refer to the field
  51
+and describe the operation.
  52
+
  53
+.. note::
  54
+
  55
+   In order to access the new value that has been saved in this way, the object
  56
+   will need to be reloaded::
  57
+
  58
+       reporter = Reporters.objects.get(pk=reporter.pk)
  59
+
  60
+As well as being used in operations on single instances as above, ``F()`` can
  61
+be used on ``QuerySets`` of object instances, with ``update()``. This reduces
  62
+the two queries we were using above - the ``get()`` and the
  63
+:meth:`~Model.save()` - to just one::
  64
+
  65
+    reporter = Reporters.objects.filter(name='Tintin')
  66
+    reporter.update(stories_filed=F('stories_filed') + 1)
  67
+
  68
+We can also use :meth:`~django.db.models.query.QuerySet.update()` to increment
  69
+the field value on multiple objects - which could be very much faster than
  70
+pulling them all into Python from the database, looping over them, incrementing
  71
+the field value of each one, and saving each one back to the database::
  72
+
  73
+    Reporter.objects.all().update(stories_filed=F('stories_filed) + 1)
  74
+
  75
+``F()`` therefore can offer performance advantages by:
  76
+
  77
+* getting the database, rather than Python, to do work
  78
+* reducing the number of queries some operations require
  79
+
  80
+.. _avoiding-race-conditions-using-f:
  81
+
  82
+Avoiding race conditions using ``F()``
  83
+--------------------------------------
  84
+
  85
+Another useful benefit of ``F()`` is that having the database - rather than
  86
+Python - update a field's value avoids a *race condition*.
  87
+
  88
+If two Python threads execute the code in the first example above, one thread
  89
+could retrieve, increment, and save a field's value after the other has
  90
+retrieved it from the database. The value that the second thread saves will be
  91
+based on the original value; the work of the first thread will simply be lost.
  92
+
  93
+If the database is responsible for updating the field, the process is more
  94
+robust: it will only ever update the field based on the value of the field in
  95
+the database when the :meth:`~Model.save()` or ``update()`` is executed, rather
  96
+than based on its value when the instance was retrieved.
  97
+
  98
+Using ``F()`` in filters
  99
+------------------------
  100
+
  101
+``F()`` is also very useful in ``QuerySet`` filters, where they make it
  102
+possible to filter a set of objects against criteria based on their field
  103
+values, rather than on Python values.
  104
+
  105
+This is documented in :ref:`using F() expressions in queries
  106
+<using-f-expressions-in-filters>`
  107
+
  108
+Supported operations with ``F()``
  109
+---------------------------------
  110
+
  111
+As well as addition, Django supports subtraction, multiplication, division,
  112
+and modulo arithmetic with ``F()`` objects, using Python constants,
  113
+variables, and even other ``F()`` objects.
  114
+
  115
+``Q()`` objects
  116
+===============
  117
+
  118
+.. class:: Q
  119
+
  120
+A ``Q()`` object, like an :class:`~django.db.models.F` object, encapsulates a
  121
+SQL expression in a Python object that can be used in database-related
  122
+operations.
  123
+
  124
+In general, ``Q() objects`` make it possible to define and reuse conditions.
  125
+This permits the :ref:`construction of complex database queries
  126
+<complex-lookups-with-q>` using ``|`` (``OR``) and ``&`` (``AND``) operators;
  127
+in particular, it is not otherwise possible to use ``OR`` in ``QuerySets``.
6  docs/releases/1.1-alpha-1.txt
@@ -46,15 +46,15 @@ Query expressions
46 46
 Queries can now refer to a another field on the query and can traverse
47 47
 relationships to refer to fields on related models. This is implemented in the
48 48
 new :class:`F` object; for full details, including examples, consult the
49  
-:ref:`documentation for F expressions <query-expressions>`.
  49
+:class:`F expressions documentation <django.db.models.F>`.
50 50
 
51 51
 Performance improvements
52 52
 ------------------------
53 53
 
54 54
 .. currentmodule:: django.test
55 55
 
56  
-Tests written using Django's :doc:`testing framework </topics/testing/index>` now run
57  
-dramatically faster (as much as 10 times faster in many cases).
  56
+Tests written using Django's :doc:`testing framework </topics/testing/index>`
  57
+now run dramatically faster (as much as 10 times faster in many cases).
58 58
 
59 59
 This was accomplished through the introduction of transaction-based tests: when
60 60
 using :class:`django.test.TestCase`, your tests will now be run in a transaction
2  docs/releases/1.1.txt
@@ -211,7 +211,7 @@ Query expressions
211 211
 Queries can now refer to a another field on the query and can traverse
212 212
 relationships to refer to fields on related models. This is implemented in the
213 213
 new :class:`~django.db.models.F` object; for full details, including examples,
214  
-consult the :ref:`documentation for F expressions <query-expressions>`.
  214
+consult the :class:`F expressions documentation <django.db.models.F>`.
215 215
 
216 216
 Model improvements
217 217
 ------------------
2  docs/releases/1.3.txt
@@ -324,7 +324,7 @@ requests. These include:
324 324
   to :meth:`~django.shortcuts.render_to_response()` providing a
325 325
   :class:`~django.template.RequestContext` by default.
326 326
 
327  
-* Support for combining :ref:`F() expressions <query-expressions>`
  327
+* Support for combining :class:`F expressions <django.db.models.F>`
328 328
   with timedelta values when retrieving or updating database values.
329 329
 
330 330
 .. _HTTPOnly: https://www.owasp.org/index.php/HTTPOnly
11  docs/releases/1.5-alpha-1.txt
@@ -562,11 +562,12 @@ Miscellaneous
562 562
   needs. The new default value is ``0666`` (octal) and the current umask value
563 563
   is first masked out.
564 564
 
565  
-* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
566  
-  ``&`` and ``|``. These operators are now available using ``.bitand()`` and
567  
-  ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
568  
-  :ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
569  
-  the operators are used as boolean AND and OR operators.
  565
+* The :class:`F expressions <django.db.models.F>` supported bitwise operators
  566
+  by ``&`` and ``|``. These operators are now available using ``.bitand()`` and
  567
+  ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be
  568
+  consistent with :ref:`Q() expressions <complex-lookups-with-q>` and
  569
+  ``QuerySet`` combining where the operators are used as boolean AND and OR
  570
+  operators.
570 571
 
571 572
 * The :ttag:`csrf_token` template tag is no longer enclosed in a div. If you need
572 573
   HTML validation against pre-HTML5 Strict DTDs, you should add a div around it
11  docs/releases/1.5-beta-1.txt
@@ -601,13 +601,14 @@ Miscellaneous
601 601
   needs. The new default value is ``0666`` (octal) and the current umask value
602 602
   is first masked out.
603 603
 
604  
-* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
  604
+* The :class:`F expressions <django.db.models.F>` supported bitwise operators by
605 605
   ``&`` and ``|``. These operators are now available using ``.bitand()`` and
606  
-  ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
607  
-  :ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
608  
-  the operators are used as boolean AND and OR operators.
  606
+  ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be
  607
+  consistent with :ref:`Q() expressions <complex-lookups-with-q>` and
  608
+  ``QuerySet`` combining where the operators are used as boolean AND and OR
  609
+  operators.
609 610
 
610  
-* In a ``filter()`` call, when :ref:`F() expressions <query-expressions>`
  611
+* In a ``filter()`` call, when :class:`F expressions <django.db.models.F>`
611 612
   contained lookups spanning multi-valued relations, they didn't always reuse
612 613
   the same relations as other lookups along the same chain. This was changed,
613 614
   and now F() expressions will always use the same relations as other lookups
11  docs/releases/1.5.txt
@@ -679,13 +679,14 @@ Miscellaneous
679 679
   needs. The new default value is ``0666`` (octal) and the current umask value
680 680
   is first masked out.
681 681
 
682  
-* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
  682
+* The :class:`F expressions <django.db.models.F>` supported bitwise operators by
683 683
   ``&`` and ``|``. These operators are now available using ``.bitand()`` and
684  
-  ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
685  
-  :ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
686  
-  the operators are used as boolean AND and OR operators.
  684
+  ``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be
  685
+  consistent with :ref:`Q() expressions <complex-lookups-with-q>` and
  686
+  ``QuerySet`` combining where the operators are used as boolean AND and OR
  687
+  operators.
687 688
 
688  
-* In a ``filter()`` call, when :ref:`F() expressions <query-expressions>`
  689
+* In a ``filter()`` call, when :class:`F expressions <django.db.models.F>`
689 690
   contained lookups spanning multi-valued relations, they didn't always reuse
690 691
   the same relations as other lookups along the same chain. This was changed,
691 692
   and now F() expressions will always use the same relations as other lookups
2  docs/topics/db/optimization.txt
@@ -111,7 +111,7 @@ For instance:
111 111
 * At the most basic level, use :ref:`filter and exclude <queryset-api>` to do
112 112
   filtering in the database.
113 113
 
114  
-* Use :ref:`F() object query expressions <query-expressions>` to do filtering
  114
+* Use :class:`F expressions <django.db.models.F>` to do filtering
115 115
   against other fields within the same model.
116 116
 
117 117
 * Use :doc:`annotate to do aggregation in the database </topics/db/aggregation>`.
22  docs/topics/db/queries.txt
@@ -588,18 +588,16 @@ relation). Conditions in subsequent
588 588
 :meth:`~django.db.models.query.QuerySet.exclude` calls that refer to the same
589 589
 relation may end up filtering on different linked objects.
590 590
 
591  
-.. _query-expressions:
  591
+.. _using-f-expressions-in-filters:
592 592
 
593 593
 Filters can reference fields on the model
594 594
 -----------------------------------------
595 595
 
596  
-.. class:: F
597  
-
598 596
 In the examples given so far, we have constructed filters that compare
599 597
 the value of a model field with a constant. But what if you want to compare
600 598
 the value of a model field with another field on the same model?
601 599
 
602  
-Django provides the :ref:`F() expressions <query-expressions>` to allow such
  600
+Django provides :class:`F expressions <django.db.models.F>` to allow such
603 601
 comparisons. Instances of ``F()`` act as a reference to a model field within a
604 602
 query. These references can then be used in query filters to compare the values
605 603
 of two different fields on the same model instance.
@@ -779,15 +777,11 @@ being evaluated and therefore populate the cache::
779 777
 Complex lookups with Q objects
780 778
 ==============================
781 779
 
782  
-.. class:: Q
783  
-
784 780
 Keyword argument queries -- in :meth:`~django.db.models.query.QuerySet.filter`,
785 781
 etc. -- are "AND"ed together. If you need to execute more complex queries (for
786  
-example, queries with ``OR`` statements), you can use ``Q`` objects.
787  
-
788  
-.. comment: Link to Q does not work, since this documentation does not exist yet.
  782
+example, queries with ``OR`` statements), you can use :class:`Q objects <django.db.models.Q>`.
789 783
 
790  
-A :class:`~django.db.models.Q` object (``django.db.models.Q``) is an object
  784
+A :class:`Q object <django.db.models.Q>` (``django.db.models.Q``) is an object
791 785
 used to encapsulate a collection of keyword arguments. These keyword arguments
792 786
 are specified as in "Field lookups" above.
793 787
 
@@ -1019,10 +1013,10 @@ over them and call :meth:`~django.db.models.Model.save`::
1019 1013
     for item in my_queryset:
1020 1014
         item.save()
1021 1015
 
1022  
-Calls to update can also use :ref:`F() objects <query-expressions>` to update
1023  
-one field based on the value of another field in the model. This is especially
1024  
-useful for incrementing counters based upon their current value. For example, to
1025  
-increment the pingback count for every entry in the blog::
  1016
+Calls to update can also use :class:`F expressions <django.db.models.F>` to
  1017
+update one field based on the value of another field in the model. This is
  1018
+especially useful for incrementing counters based upon their current value. For
  1019
+example, to increment the pingback count for every entry in the blog::
1026 1020
 
1027 1021
     >>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
1028 1022
 

0 notes on commit 263eecc

Please sign in to comment.
Something went wrong with that request. Please try again.