Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Browse files

Fixed #11527 -- Added unit tests and documentation for the use of F()…

… expressions in single object updates. Thanks to Zachary Voase for the patch.

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b2f72fc0405e966a5c4dbce23e84a43d80db3614 1 parent 007bfdd
@freakboy3742 freakboy3742 authored
1  AUTHORS
@@ -439,6 +439,7 @@ answer newbie questions, and generally made Django that much better:
George Vilches <>
Vlado <>
+ Zachary Voase <>
Milton Waddams
Chris Wagner <>
Rick Wagner <>
42 docs/ref/models/instances.txt
@@ -188,6 +188,46 @@ almost always do the right thing and trying to override that will lead to
errors that are difficult to track down. This feature is for advanced use
+Updating attributes based on existing fields
+Sometimes you'll need to perform a simple arithmetic task on a field, such
+as incrementing or decrementing the current value. The obvious way to
+achieve this is to do something like::
+ >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
+ >>> product.number_sold += 1
+ >>>
+If the old ``number_sold`` value retrieved from the database was 10, then
+the value of 11 will be written back to the database.
+This can be optimized slightly by expressing the update relative to the
+original field value, rather than as an explicit assignment of a new value.
+Django provides :ref:`F() expressions <query-expressions>` as a way of
+performing this kind of relative update. Using ``F()`` expressions, the
+previous example would be expressed as::
+ >>> from django.db.models import F
+ >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
+ >>> product.number_sold = F('number_sold') + 1
+ >>>
+This approach doesn't use the initial value from the database. Instead, it
+makes the database do the update based on whatever value is current at the
+time that the 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(
+ >>> print product.number_sold
+ 42
+For more details, see the documentation on :ref:`F() expressions
+<query-expressions>` and their :ref:`use in update queries
Deleting objects
@@ -196,7 +236,7 @@ Deleting objects
Issues a SQL ``DELETE`` for the object. This only deletes the object in the
database; the Python instance will still be around, and will still have data
in its fields.
For more details, including how to delete objects in bulk, see
39 tests/modeltests/expressions/
@@ -80,4 +80,43 @@ def __unicode__(self):
FieldError: Joined field references are not permitted in this query
+# F expressions can be used to update attributes on single objects
+>>> test_gmbh = Company.objects.get(name='Test GmbH')
+>>> test_gmbh.num_employees
+>>> test_gmbh.num_employees = F('num_employees') + 4
+>>> test_gmbh = Company.objects.get(
+>>> test_gmbh.num_employees
+# F expressions cannot be used to update attributes which are foreign keys, or
+# attributes which involve joins.
+>>> test_gmbh.point_of_contact = None
+>>> test_gmbh.point_of_contact is None
+>>> test_gmbh.point_of_contact = F('ceo')
+Traceback (most recent call last):
+ValueError: Cannot assign "<django.db.models.expressions.F object at ...>": "Company.point_of_contact" must be a "Employee" instance.
+>>> test_gmbh.point_of_contact =
+>>> = F('ceo__last_name')
+Traceback (most recent call last):
+FieldError: Joined field references are not permitted in this query
+# F expressions cannot be used to update attributes on objects which do not yet
+# exist in the database
+>>> acme = Company(name='The Acme Widget Co.', num_employees=12, num_chairs=5,
+>>> acme.num_employees = F('num_employees') + 16
+Traceback (most recent call last):
+TypeError: int() argument must be a string or a number, not 'ExpressionNode'

0 comments on commit b2f72fc

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