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: http://code.djangoproject.com/svn/django/trunk@11322 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
007bfddc1f
commit
b2f72fc040
1
AUTHORS
1
AUTHORS
|
@ -439,6 +439,7 @@ answer newbie questions, and generally made Django that much better:
|
|||
viestards.lists@gmail.com
|
||||
George Vilches <gav@thataddress.com>
|
||||
Vlado <vlado@labath.org>
|
||||
Zachary Voase <zacharyvoase@gmail.com>
|
||||
Milton Waddams
|
||||
Chris Wagner <cw264701@ohio.edu>
|
||||
Rick Wagner <rwagner@physics.ucsd.edu>
|
||||
|
|
|
@ -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
|
||||
only.
|
||||
|
||||
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
|
||||
>>> product.save()
|
||||
|
||||
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
|
||||
>>> product.save()
|
||||
|
||||
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(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>`.
|
||||
|
||||
Deleting objects
|
||||
================
|
||||
|
||||
|
|
|
@ -80,4 +80,43 @@ Traceback (most recent call last):
|
|||
...
|
||||
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
|
||||
32
|
||||
>>> test_gmbh.num_employees = F('num_employees') + 4
|
||||
>>> test_gmbh.save()
|
||||
>>> test_gmbh = Company.objects.get(pk=test_gmbh.pk)
|
||||
>>> test_gmbh.num_employees
|
||||
36
|
||||
|
||||
# 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.save()
|
||||
>>> test_gmbh.point_of_contact is None
|
||||
True
|
||||
>>> 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 = test_gmbh.ceo
|
||||
>>> test_gmbh.save()
|
||||
>>> test_gmbh.name = F('ceo__last_name')
|
||||
>>> test_gmbh.save()
|
||||
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,
|
||||
... ceo=test_gmbh.ceo)
|
||||
>>> acme.num_employees = F('num_employees') + 16
|
||||
>>> acme.save()
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: int() argument must be a string or a number, not 'ExpressionNode'
|
||||
|
||||
"""}
|
||||
|
|
Loading…
Reference in New Issue