This document provides reference material for query-related tools not documented elsewhere.
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.
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 save() - to just one:
reporter = Reporters.objects.filter(name='Tintin') reporter.update(stories_filed=F('stories_filed') + 1)
We can also use 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:
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 save() or update() is executed, rather than based on its value when the instance was retrieved.
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 using F() expressions in queries
As well as addition, Django supports subtraction, multiplication, division, and modulo arithmetic with F() objects, using Python constants, variables, and even other F() objects.
The power operator ** is also supported.
A Q() object, like an 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 construction of complex database queries using | (OR) and & (AND) operators; in particular, it is not otherwise possible to use OR in QuerySets.
The Prefetch() object can be used to control the operation of prefetch_related().
The lookup argument describes the relations to follow and works the same as the string based lookups passed to 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 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.
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.
Введите слова для поиска или имя модуля, класса или функции.
Mar 30, 2016