Consolidated documentation for F() and Q()
This commit is contained in:
parent
bd8e1a354c
commit
79cc66692a
|
@ -65,7 +65,8 @@ manipulating the data of your Web application. Learn more about it below:
|
||||||
|
|
||||||
* **QuerySets:**
|
* **QuerySets:**
|
||||||
:doc:`Executing queries <topics/db/queries>` |
|
:doc:`Executing queries <topics/db/queries>` |
|
||||||
:doc:`QuerySet method reference <ref/models/querysets>`
|
:doc:`QuerySet method reference <ref/models/querysets>` |
|
||||||
|
:doc:`Query-related classes <ref/models/queries>`
|
||||||
|
|
||||||
* **Model instances:**
|
* **Model instances:**
|
||||||
:doc:`Instance methods <ref/models/instances>` |
|
:doc:`Instance methods <ref/models/instances>` |
|
||||||
|
|
|
@ -1062,11 +1062,12 @@ define the details of how the relation works.
|
||||||
only allows the choice of related objects with a ``pub_date`` before the
|
only allows the choice of related objects with a ``pub_date`` before the
|
||||||
current date to be chosen.
|
current date to be chosen.
|
||||||
|
|
||||||
Instead of a dictionary this can also be a :class:`~django.db.models.Q`
|
Instead of a dictionary this can also be a :class:`Q object
|
||||||
object for more :ref:`complex queries <complex-lookups-with-q>`. However,
|
<django.db.models.Q>` for more :ref:`complex queries
|
||||||
if ``limit_choices_to`` is a :class:`~django.db.models.Q` object then it
|
<complex-lookups-with-q>`. However, if ``limit_choices_to`` is a :class:`Q
|
||||||
will only have an effect on the choices available in the admin when the
|
object <django.db.models.Q>` then it will only have an effect on the
|
||||||
field is not listed in ``raw_id_fields`` in the ``ModelAdmin`` for the model.
|
choices available in the admin when the field is not listed in
|
||||||
|
``raw_id_fields`` in the ``ModelAdmin`` for the model.
|
||||||
|
|
||||||
.. attribute:: ForeignKey.related_name
|
.. attribute:: ForeignKey.related_name
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,4 @@ Model API reference. For introductory material, see :doc:`/topics/db/models`.
|
||||||
options
|
options
|
||||||
instances
|
instances
|
||||||
querysets
|
querysets
|
||||||
|
queries
|
||||||
|
|
|
@ -342,6 +342,8 @@ only.
|
||||||
|
|
||||||
Using ``update_fields`` will force an update similarly to ``force_update``.
|
Using ``update_fields`` will force an update similarly to ``force_update``.
|
||||||
|
|
||||||
|
.. _ref-models-field-updates-using-f-expressions:
|
||||||
|
|
||||||
Updating attributes based on existing fields
|
Updating attributes based on existing fields
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
@ -356,35 +358,21 @@ achieve this is to do something like::
|
||||||
If the old ``number_sold`` value retrieved from the database was 10, then
|
If the old ``number_sold`` value retrieved from the database was 10, then
|
||||||
the value of 11 will be written back to the database.
|
the value of 11 will be written back to the database.
|
||||||
|
|
||||||
This sequence has a standard update problem in that it contains a race
|
The process can be made robust, :ref:`avoiding a race condition
|
||||||
condition. If another thread of execution has already saved an updated value
|
<avoiding-race-conditions-using-f>`, as well as slightly faster by expressing
|
||||||
after the current thread retrieved the old value, the current thread will only
|
the update relative to the original field value, rather than as an explicit
|
||||||
save the old value plus one, rather than the new (current) value plus one.
|
assignment of a new value. Django provides :class:`F expressions
|
||||||
|
<django.db.models.F>` for performing this kind of relative update. Using
|
||||||
The process can be made robust and slightly faster by expressing the update
|
:class:`F expressions <django.db.models.F>`, the previous example is expressed
|
||||||
relative to the original field value, rather than as an explicit assignment of
|
as::
|
||||||
a new value. Django provides :ref:`F() expressions <query-expressions>` for
|
|
||||||
performing this kind of relative update. Using ``F()`` expressions, the
|
|
||||||
previous example is expressed as::
|
|
||||||
|
|
||||||
>>> from django.db.models import F
|
>>> from django.db.models import F
|
||||||
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
|
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
|
||||||
>>> product.number_sold = F('number_sold') + 1
|
>>> product.number_sold = F('number_sold') + 1
|
||||||
>>> product.save()
|
>>> product.save()
|
||||||
|
|
||||||
This approach doesn't use the initial value from the database. Instead, it
|
For more details, see the documentation on :class:`F expressions
|
||||||
makes the database do the update based on whatever value is current at the time
|
<django.db.models.F>` and their :ref:`use in update queries
|
||||||
that the :meth:`~Model.save()` is executed.
|
|
||||||
|
|
||||||
Once the object has been saved, you must reload the object in order to access
|
|
||||||
the actual value that was applied to the updated field::
|
|
||||||
|
|
||||||
>>> product = Products.objects.get(pk=product.pk)
|
|
||||||
>>> print(product.number_sold)
|
|
||||||
42
|
|
||||||
|
|
||||||
For more details, see the documentation on :ref:`F() expressions
|
|
||||||
<query-expressions>` and their :ref:`use in update queries
|
|
||||||
<topics-db-queries-update>`.
|
<topics-db-queries-update>`.
|
||||||
|
|
||||||
Specifying which fields to save
|
Specifying which fields to save
|
||||||
|
|
|
@ -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``.
|
|
@ -46,15 +46,15 @@ Query expressions
|
||||||
Queries can now refer to a another field on the query and can traverse
|
Queries can now refer to a another field on the query and can traverse
|
||||||
relationships to refer to fields on related models. This is implemented in the
|
relationships to refer to fields on related models. This is implemented in the
|
||||||
new :class:`F` object; for full details, including examples, consult the
|
new :class:`F` object; for full details, including examples, consult the
|
||||||
:ref:`documentation for F expressions <query-expressions>`.
|
:class:`F expressions documentation <django.db.models.F>`.
|
||||||
|
|
||||||
Performance improvements
|
Performance improvements
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
.. currentmodule:: django.test
|
.. currentmodule:: django.test
|
||||||
|
|
||||||
Tests written using Django's :doc:`testing framework </topics/testing/index>` now run
|
Tests written using Django's :doc:`testing framework </topics/testing/index>`
|
||||||
dramatically faster (as much as 10 times faster in many cases).
|
now run dramatically faster (as much as 10 times faster in many cases).
|
||||||
|
|
||||||
This was accomplished through the introduction of transaction-based tests: when
|
This was accomplished through the introduction of transaction-based tests: when
|
||||||
using :class:`django.test.TestCase`, your tests will now be run in a transaction
|
using :class:`django.test.TestCase`, your tests will now be run in a transaction
|
||||||
|
|
|
@ -211,7 +211,7 @@ Query expressions
|
||||||
Queries can now refer to a another field on the query and can traverse
|
Queries can now refer to a another field on the query and can traverse
|
||||||
relationships to refer to fields on related models. This is implemented in the
|
relationships to refer to fields on related models. This is implemented in the
|
||||||
new :class:`~django.db.models.F` object; for full details, including examples,
|
new :class:`~django.db.models.F` object; for full details, including examples,
|
||||||
consult the :ref:`documentation for F expressions <query-expressions>`.
|
consult the :class:`F expressions documentation <django.db.models.F>`.
|
||||||
|
|
||||||
Model improvements
|
Model improvements
|
||||||
------------------
|
------------------
|
||||||
|
|
|
@ -324,7 +324,7 @@ requests. These include:
|
||||||
to :meth:`~django.shortcuts.render_to_response()` providing a
|
to :meth:`~django.shortcuts.render_to_response()` providing a
|
||||||
:class:`~django.template.RequestContext` by default.
|
:class:`~django.template.RequestContext` by default.
|
||||||
|
|
||||||
* Support for combining :ref:`F() expressions <query-expressions>`
|
* Support for combining :class:`F expressions <django.db.models.F>`
|
||||||
with timedelta values when retrieving or updating database values.
|
with timedelta values when retrieving or updating database values.
|
||||||
|
|
||||||
.. _HTTPOnly: https://www.owasp.org/index.php/HTTPOnly
|
.. _HTTPOnly: https://www.owasp.org/index.php/HTTPOnly
|
||||||
|
|
|
@ -562,11 +562,12 @@ Miscellaneous
|
||||||
needs. The new default value is ``0666`` (octal) and the current umask value
|
needs. The new default value is ``0666`` (octal) and the current umask value
|
||||||
is first masked out.
|
is first masked out.
|
||||||
|
|
||||||
* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
|
* The :class:`F expressions <django.db.models.F>` supported bitwise operators
|
||||||
``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
by ``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
||||||
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
|
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be
|
||||||
:ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
|
consistent with :ref:`Q() expressions <complex-lookups-with-q>` and
|
||||||
the operators are used as boolean AND and OR operators.
|
``QuerySet`` combining where the operators are used as boolean AND and OR
|
||||||
|
operators.
|
||||||
|
|
||||||
* The :ttag:`csrf_token` template tag is no longer enclosed in a div. If you need
|
* The :ttag:`csrf_token` template tag is no longer enclosed in a div. If you need
|
||||||
HTML validation against pre-HTML5 Strict DTDs, you should add a div around it
|
HTML validation against pre-HTML5 Strict DTDs, you should add a div around it
|
||||||
|
|
|
@ -601,13 +601,14 @@ Miscellaneous
|
||||||
needs. The new default value is ``0666`` (octal) and the current umask value
|
needs. The new default value is ``0666`` (octal) and the current umask value
|
||||||
is first masked out.
|
is first masked out.
|
||||||
|
|
||||||
* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
|
* The :class:`F expressions <django.db.models.F>` supported bitwise operators by
|
||||||
``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
||||||
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
|
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be
|
||||||
:ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
|
consistent with :ref:`Q() expressions <complex-lookups-with-q>` and
|
||||||
the operators are used as boolean AND and OR operators.
|
``QuerySet`` combining where the operators are used as boolean AND and OR
|
||||||
|
operators.
|
||||||
|
|
||||||
* In a ``filter()`` call, when :ref:`F() expressions <query-expressions>`
|
* In a ``filter()`` call, when :class:`F expressions <django.db.models.F>`
|
||||||
contained lookups spanning multi-valued relations, they didn't always reuse
|
contained lookups spanning multi-valued relations, they didn't always reuse
|
||||||
the same relations as other lookups along the same chain. This was changed,
|
the same relations as other lookups along the same chain. This was changed,
|
||||||
and now F() expressions will always use the same relations as other lookups
|
and now F() expressions will always use the same relations as other lookups
|
||||||
|
|
|
@ -679,13 +679,14 @@ Miscellaneous
|
||||||
needs. The new default value is ``0666`` (octal) and the current umask value
|
needs. The new default value is ``0666`` (octal) and the current umask value
|
||||||
is first masked out.
|
is first masked out.
|
||||||
|
|
||||||
* The :ref:`F() expressions <query-expressions>` supported bitwise operators by
|
* The :class:`F expressions <django.db.models.F>` supported bitwise operators by
|
||||||
``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
``&`` and ``|``. These operators are now available using ``.bitand()`` and
|
||||||
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be consistent with
|
``.bitor()`` instead. The removal of ``&`` and ``|`` was done to be
|
||||||
:ref:`Q() expressions <complex-lookups-with-q>` and ``QuerySet`` combining where
|
consistent with :ref:`Q() expressions <complex-lookups-with-q>` and
|
||||||
the operators are used as boolean AND and OR operators.
|
``QuerySet`` combining where the operators are used as boolean AND and OR
|
||||||
|
operators.
|
||||||
|
|
||||||
* In a ``filter()`` call, when :ref:`F() expressions <query-expressions>`
|
* In a ``filter()`` call, when :class:`F expressions <django.db.models.F>`
|
||||||
contained lookups spanning multi-valued relations, they didn't always reuse
|
contained lookups spanning multi-valued relations, they didn't always reuse
|
||||||
the same relations as other lookups along the same chain. This was changed,
|
the same relations as other lookups along the same chain. This was changed,
|
||||||
and now F() expressions will always use the same relations as other lookups
|
and now F() expressions will always use the same relations as other lookups
|
||||||
|
|
|
@ -111,7 +111,7 @@ For instance:
|
||||||
* At the most basic level, use :ref:`filter and exclude <queryset-api>` to do
|
* At the most basic level, use :ref:`filter and exclude <queryset-api>` to do
|
||||||
filtering in the database.
|
filtering in the database.
|
||||||
|
|
||||||
* Use :ref:`F() object query expressions <query-expressions>` to do filtering
|
* Use :class:`F expressions <django.db.models.F>` to do filtering
|
||||||
against other fields within the same model.
|
against other fields within the same model.
|
||||||
|
|
||||||
* Use :doc:`annotate to do aggregation in the database </topics/db/aggregation>`.
|
* Use :doc:`annotate to do aggregation in the database </topics/db/aggregation>`.
|
||||||
|
|
|
@ -588,18 +588,16 @@ relation). Conditions in subsequent
|
||||||
:meth:`~django.db.models.query.QuerySet.exclude` calls that refer to the same
|
:meth:`~django.db.models.query.QuerySet.exclude` calls that refer to the same
|
||||||
relation may end up filtering on different linked objects.
|
relation may end up filtering on different linked objects.
|
||||||
|
|
||||||
.. _query-expressions:
|
.. _using-f-expressions-in-filters:
|
||||||
|
|
||||||
Filters can reference fields on the model
|
Filters can reference fields on the model
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
.. class:: F
|
|
||||||
|
|
||||||
In the examples given so far, we have constructed filters that compare
|
In the examples given so far, we have constructed filters that compare
|
||||||
the value of a model field with a constant. But what if you want to compare
|
the value of a model field with a constant. But what if you want to compare
|
||||||
the value of a model field with another field on the same model?
|
the value of a model field with another field on the same model?
|
||||||
|
|
||||||
Django provides the :ref:`F() expressions <query-expressions>` to allow such
|
Django provides :class:`F expressions <django.db.models.F>` to allow such
|
||||||
comparisons. Instances of ``F()`` act as a reference to a model field within a
|
comparisons. Instances of ``F()`` act as a reference to a model field within a
|
||||||
query. These references can then be used in query filters to compare the values
|
query. These references can then be used in query filters to compare the values
|
||||||
of two different fields on the same model instance.
|
of two different fields on the same model instance.
|
||||||
|
@ -779,15 +777,11 @@ being evaluated and therefore populate the cache::
|
||||||
Complex lookups with Q objects
|
Complex lookups with Q objects
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
.. class:: Q
|
|
||||||
|
|
||||||
Keyword argument queries -- in :meth:`~django.db.models.query.QuerySet.filter`,
|
Keyword argument queries -- in :meth:`~django.db.models.query.QuerySet.filter`,
|
||||||
etc. -- are "AND"ed together. If you need to execute more complex queries (for
|
etc. -- are "AND"ed together. If you need to execute more complex queries (for
|
||||||
example, queries with ``OR`` statements), you can use ``Q`` objects.
|
example, queries with ``OR`` statements), you can use :class:`Q objects <django.db.models.Q>`.
|
||||||
|
|
||||||
.. comment: Link to Q does not work, since this documentation does not exist yet.
|
A :class:`Q object <django.db.models.Q>` (``django.db.models.Q``) is an object
|
||||||
|
|
||||||
A :class:`~django.db.models.Q` object (``django.db.models.Q``) is an object
|
|
||||||
used to encapsulate a collection of keyword arguments. These keyword arguments
|
used to encapsulate a collection of keyword arguments. These keyword arguments
|
||||||
are specified as in "Field lookups" above.
|
are specified as in "Field lookups" above.
|
||||||
|
|
||||||
|
@ -1019,10 +1013,10 @@ over them and call :meth:`~django.db.models.Model.save`::
|
||||||
for item in my_queryset:
|
for item in my_queryset:
|
||||||
item.save()
|
item.save()
|
||||||
|
|
||||||
Calls to update can also use :ref:`F() objects <query-expressions>` to update
|
Calls to update can also use :class:`F expressions <django.db.models.F>` to
|
||||||
one field based on the value of another field in the model. This is especially
|
update one field based on the value of another field in the model. This is
|
||||||
useful for incrementing counters based upon their current value. For example, to
|
especially useful for incrementing counters based upon their current value. For
|
||||||
increment the pingback count for every entry in the blog::
|
example, to increment the pingback count for every entry in the blog::
|
||||||
|
|
||||||
>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
|
>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue