Django的F()表达式

算是一些基本的高级用法吧,在Django文档的Query-related classes这一章中。主要讲了三个类,F(),Q()prefetch()。我们下面讲一讲F()

class F()
F()是代表模型字段的值,也就是说对于一些特殊的字段的操作,我们不需要用python把数据先取到内存中,然后操作,在存储到db中了。

##常见的使用场景

###字段加1(加减乘除运算)

例如我们有个统计点击量的字段,每次更新的操作其实就是把字段的值加1.

一般我们的做法是把这条记录取出来,把相应字段加+1,然后在save,类似下面的代码

# Tintin filed a news story!
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()

当我们使用了F()之后呢? 只需要一行代码

Reporters.objects.filter(name='Tintin').update(stories_filed=F('stories_filed') + 1)

不仅代码量少了,而且这是直接在数据中操作,效率也变高了,特别是并发的情况,减少了多线程同时操作带来的隐患。 但是不支持字符串相加的操作

###字段比较
例如一个合同有两个日期,一个叫做终止日期,一个叫做结束日期,现在要筛选出终止日期小于结束日期的合同。

from django.db.models import F
from contracts.models import Contracts
contracts = Contracts.objects.filter(contract_stop_time__lt=F('end_time'))

如果没有F对象,就没法直接使用rom来查询。

###补充–通过F()避免竞态条件

Another useful benefit of F() is that having the database - rather than Python - update a field’s value avoids a race condition.

If two Python threads execute the code in the first example above, one thread could retrieve, increment, and save a field’s value after the other has retrieved it from the database. The value that the second thread saves will be based on the original value; the work of the first thread will simply be lost.

If the database is responsible for updating the field, the process is more robust: it will only ever update the field based on the value of the field in the database when the save() or update() is executed, rather than based on its value when the instance was retrieved.