(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 <[email protected]> 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
>
> --
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/django-developers.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>

-- 
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 [email protected].
To post to this group, send email to [email protected].
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