目录
F查询
使用 F()
避免竞争条件
F()
可以通过以下方式提供性能优势:
- 让数据库,而不是 Python 来完成工作, 避免了 竞争条件
- 减少某些操作所需的查询次数
如果两个 Python 线程执行修改一个字段的值的代码,一个线程可以在另一个线程从数据库中获取一个字段的值后,检索、递增并保存它。第二个线程保存的值将基于原始值,第一个线程的工作将丢失。
如果数据库负责更新字段,那么这个过程就比较稳健:它只会在执行 save()
或 update()
时,根据数据库中字段的值来更新字段,而不是根据检索实例时的值来更新。
F() 赋值在 Model.save() 之后持续存在
F()
分配给模型字段的对象在保存模型实例后会持续存在,并将应用于每个 save()
。例如:
obj = Book.objects.get(pk=12)
print(obj.price) # 10
obj.price = F('price') + 1
obj.save()
obj.name = '福尔摩5'
obj.save() # 此时数据库里的price已经是12了
在这种情况下,stories_filed
将被更新两次。如果最初是 1
,最终值将是 3
。这种持久性可以通过在保存模型对象后重新加载来避免,例如,使用 refresh_from_db()
。
F对时间加减
对于 date 和 date/time 字段,你可以加上或减去一个 timedelta
对象。以下会返回所有发布 3 天后被修改的条目:
>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
查找Entry
在上次修改的同一年发布的所有对象:
>>> Entry.objects.filter(pub_date__year=F('mod_date__year'))
与annotate一起使用F()
F()
可用于通过将不同的字段与算术相结合,在你的模型上创建动态字段:
company = Company.objects.annotate(
chairs_needed=F('num_employees') - F('num_chairs'))
如果你要组合的字段是不同类型的,你需要告诉 Django 将返回什么样的字段。由于 F()
不直接支持 output_field
,你需要用[ExpressionWrapper
来包装表达式:
from django.db.models import DateTimeField, ExpressionWrapper, F
Ticket.objects.annotate(
expires=ExpressionWrapper(
# 活动时间 持续时间
F('active_at') + F('duration'), output_field=DateTimeField()))
标签:obj,查询,annotate,objects,线程,django,date,save
From: https://www.cnblogs.com/zonghan/p/17039595.html