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 <[email protected] <mailto:[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
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 [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.
