On 14/08/13 10:05, Marc Tamlyn wrote:
(Disclaimer: I didn't write any of this code, I'm just working from my
own possibly flawed understanding)

The main point of using F is not generally for performance per se,
rather for database consistency. In the first example, the performance
increase is negligable, but you get two significant benefits. The first
is that you minimise the risk of race conditions by effectively issuing
"increment" rather than "set" to the database. The second is that you
can increase a number of rows the same way -
Product.objects.update(number_sold=F('number_sold') + 1). These add
performance in that you end up doing fewer queries, but that's actually
what you're gaining.

It is worth noting that the *only* reason to set an attribute to be an F
expression is to then update the value in the database. In fact, you
cannot access the value after you've done this, you get a
"django.db.models.expressions.ExpressionNode" instance. In that sense,
doing product.number_sold = F('number_sold') + 1 is really a long hand
version of the update() query.

As for what expressions are valid, I believe the things you suggested do
work, but I imagine exactly what works will depend on what operations
the database (and backend) support. Django itself isn't doing anything
clever here, it's just providing some architecture to allow you to
delegate functionality to the database.

I agree that the main documentation for F() should reference the update
case (IMO as an update() rather than the longhand version).

Marc


On 13 August 2013 20:22, Daniele Procida <dani...@vurt.org
<mailto:dani...@vurt.org>> wrote:

    I noticed while looking for material for
    <https://code.djangoproject.com/ticket/20877> that
    
<https://docs.djangoproject.com/en/dev/models/instances.html#updating-attributes-based-on-existing-fields/>
    mentions that:

         product.number_sold = F('number_sold') + 1

    is faster than:

         product.number_sold += 1

    though this doesn't seem to be mentioned in the database
    optimisation page.

    That's easy enough to address, and
    
<https://docs.djangoproject.com/en/dev/topics/db/optimization.html#do-database-work-in-the-database-rather-than-in-python/>
    seems like a sensible place for it.

    However the mentions of F() that I did find raised a number of
    questions.

    The F() class seems to be a handy general-purpose way to refer to
    the value of a model field..


    Firstly, it's not explained how, in expressions like:

         product.number_sold = F('number_sold') + 1

    (from
    
<https://docs.djangoproject.com/en/dev/models/instances.html#updating-attributes-based-on-existing-fields/>)
    Django knows that F('number_sold') is refers to the product model.

    Does it know because product.number_sold is the field that this
    expression refers to? What would happen if we did:

         product.number_in_stock = F('number_in_stock') - F('number_sold)

    (i.e. can we make such calculations multiple other fields in one
    go?), or:

         product.number_to_reorder = F('number_sold)

    for example? What are the rules of the usage syntax of F()?

    Secondly, the main documentation for F()
    
<https://docs.djangoproject.com/en/dev/topics/db/queries.html#query-expressions/>
    doesn't mention this kind of use at all: it only suggests that it
    might be useful in queries.

    Since this use seems to be just one of multiple uses for F(),
    shouldn't a more general description of F() belong somewhere else
    (where) instead?


    Finally, are there any other useful ways to use F() not covered by
    these two examples?


    Daniele

I've always found the documentation on the usage of F() to be somewhat substandard compared to the rest of the documentation to the point were I rarely if ever use it.

If the documentation could be beefed up I'm sure more people would be happy to use it in the general case rather than just small side cases.

--
You received this message because you are subscribed to the Google Groups "Django 
developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to