Ticket #11527: patch-v1.diff

File patch-v1.diff, 3.6 KB (added by Zachary Voase, 15 years ago)

Initial patch. Tests pass on SQLite3.

  • tests/modeltests/expressions/models.py

     
    8080...
    8181FieldError: Joined field references are not permitted in this query
    8282
     83# F expressions can be used to update attributes on single objects
     84>>> test_gmbh = Company.objects.get(name='Test GmbH')
     85>>> test_gmbh.num_employees
     8632
     87>>> test_gmbh.num_employees = F('num_employees') + 4
     88>>> test_gmbh.save()
     89>>> test_gmbh = Company.objects.get(pk=test_gmbh.pk)
     90>>> test_gmbh.num_employees
     9136
     92
     93# F expressions cannot be used to update attributes which are foreign keys, or
     94# attributes which involve joins
     95>>> test_gmbh.point_of_contact = None
     96>>> test_gmbh.save()
     97>>> test_gmbh.point_of_contact is None
     98True
     99>>> test_gmbh.point_of_contact = F('ceo')
     100Traceback (most recent call last):
     101...
     102ValueError: Cannot assign "<django.db.models.expressions.F object at ...>": "Company.point_of_contact" must be a "Employee" instance.
     103
     104>>> test_gmbh.point_of_contact = test_gmbh.ceo
     105>>> test_gmbh.save()
     106>>> test_gmbh.name = F('ceo__last_name')
     107>>> test_gmbh.save()
     108Traceback (most recent call last):
     109...
     110FieldError: Joined field references are not permitted in this query
     111
     112# F expressions cannot be used to update attributes on objects which do not yet
     113# exist in the database
     114>>> acme = Company(name='The Acme Widget Co.', num_employees=12, num_chairs=5,
     115...     ceo=test_gmbh.ceo)
     116>>> acme.num_employees = F('num_employees') + 16
     117>>> acme.save()
     118Traceback (most recent call last):
     119...
     120TypeError: int() argument must be a string or a number, not 'ExpressionNode'
    83121"""}
  • docs/ref/models/instances.txt

     
    104104Explicitly specifying auto-primary-key values is mostly useful for bulk-saving
    105105objects, when you're confident you won't have primary-key collision.
    106106
     107Updating attributes using ``F()`` expressions
     108---------------------------------------------
     109
     110Sometimes you'll need to perform a simple arithmetic task on a field: incrementing, decrementing, multiplying or dividing. Usually in Python you would do something like this::
     111
     112    >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
     113    >>> product.number_sold += 1
     114    >>> product.save()
     115
     116However, this pattern leaves your code open to `race conditions <http://en.wikipedia.org/wiki/Race_condition#Computing>`_, which occur when two processes or threads try to update the same object at the same time. In order to avoid, this, you can use :ref:`F() expressions <query-expressions>` to place the burden of synchronization on the database, which will typically be much better at avoiding these issues due to its ACID-compliant architecture.
     117
     118Using ``F()`` expressions, the above code would instead be::
     119
     120    >>> from django.db.models import F
     121    >>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
     122    >>> product.number_sold = F('number_sold') + 1
     123    >>> product.save()
     124
     125After saving, it is necessary to reload the object in question in order to access the actual value of the updated field. This can be done quite simply::
     126
     127    >>> product = Products.objects.get(pk=product.pk)
     128
     129``F()`` expressions work only on numeric fields (such as integers and floats), and support the standard Python operators for addition, subtraction, multiplication and division.
     130
    107131What happens when you save?
    108132---------------------------
    109133
Back to Top