開發我的博客時,統計每篇文章瀏覽量的邏輯一般是這樣寫的:數據庫
post = Post.objects.get(...) post.views += 1 post.save()
上面的語句已經至關簡短了,但實際上還有更好的辦法,就是運用 F
函數:django
from django.db.models import F post = Post.objects.get(...) post.views = F('views') + 1 post.save()
看起來彷佛都差很少,可是用 F
函數有幾個顯著的好處:函數
post.view += 1
是 Python 在內存中操做的,而後再從內存把數據更新到數據庫;而 F('views') + 1
是直接操做的數據庫,減小了一個操做層級。post.view += 1
就有可能丟失其中的某些更新操做,而 F('views') + 1
因爲是直接操做數據庫,不會有丟失數據的問題。注意,正由於 F
函數沒有在內存中操做,所以更新完數據後須要從新刷新內存中的模型對象:post
... post.save() # 從新取值 post = Post.objects.get(...)
或者這樣:線程
... post.save() # 從新取值 post.refresh_from_db()
Done!code
除此以外,F
函數還支持跨字段的查找:對象
# models.py class Age(models.Model): year = models.IntegerField(default=6) month = models.IntegerField(default=10) # -------------- # 獲取全部 year > month 的數據 res = Age.objects.filter(year__gt=F('month'))
F
函數支持加,減,乘,除,取模和冪運算:內存
Age.objects.filter(year__gt=F('month') * 2) Age.objects.filter(year__gt=F('month') + F('year'))
對於日期字段,也能夠輕鬆處理:開發
>>> from datetime import timedelta >>> Entry.objects.filter(date__gt=F('pub_date') + timedelta(days=3))
跨關係的查找也是能夠的:文檔
# models.py class Person(...): name = ... class People(...): name = ... class Age(...): ... person = models.OneToOneField(Person, ...) people = models.OneToOneField(People, ...) # -------------- # 獲取全部 person.name == user.name 的數據 res = Age.objects.filter(person__name=F('people__name'))
F
函數還有一些更高級的用法,如與聚合的配合,這裏就不列舉了,有興趣的能夠前往文檔觀摩。