Django DB Models F 组合表达式
Posted
技术标签:
【中文标题】Django DB Models F 组合表达式【英文标题】:Django DB Models F Combined Expression 【发布时间】:2016-02-13 20:45:00 【问题描述】:In [1]: from django.db.models import F
In [2]: from forum.models import Post
In [3]: post = Post.objects.get(id=1)
In [4]: post.view_count = F('view_count') + 1
In [5]: post.save()
In [6]: post.view_count
Out[6]: <CombinedExpression: F(view_count) + Value(1)>
In [7]: post = Post.objects.get(id=1)
In [8]: post.view_count
Out[8]: 3
帖子保存后,返回组合表达式。
我想要确切的结果 (3)。
是否可以不用再次调用get方法/refresh_from_db?
【问题讨论】:
【参考方案1】:在 Django 1.8+ 中,您可以使用 refresh_from_db
方法。它不会保存任何 SQL 查询,但您可能会认为代码更好。
>>> post = Post.objects.get(id=1)
>>> post.view_count
2
>>> post.view_count = F('view_count') + 1
>>> post.save()
>>> post.refresh_from_db()
>>> post.view_count
3
由于更新发生在数据库中,如果不执行 get()
或 refresh_from_db
(这两者都会导致类似的 SQL 查询),就无法在 Django 中获取新值。但是,可以改用update()
来避免最初的get()
。
>>> Post.objects.filter(id=1).update(view_count=F('view_count') + 1)
>>> post = Post.objects.get(id=1)
>>> post.view_count
3
【讨论】:
谢谢,刷新或重新加载数据库模型需要时间吗?我像下面这样使用 post.refresh_from_db(fields=['view_count',]) 我不确定你的问题是什么。您想知道refresh_from_db()
或get()
是否需要更长的时间?
不,我不是在比较 get() 和 refresh_from_db()。一般10k用户一次更新值,view count的反应是慢还是正常?
你需要做一些性能测试,我不知道它对 10k 用户的表现如何。【参考方案2】:
来自文档https://docs.djangoproject.com/en/1.7/ref/models/queries/#f-expressions,
Python 永远不会知道封装的 SQL 表达式 post.view_count = F('view_count') + 1 # F('view_count') Django sql expression
。
完全由数据库处理。
因此,在 Python 中对数据库所做的更改都知道您应用的表达式而不是结果。
你可以直接这样操作:-
post = Post.objects.filter(id=1)
post.update(view_count = F('view_count') + 1)
【讨论】:
它会引发属性错误:AttributeError: 'Post' object has no attribute 'update'。更新将工作查询集对象列表。在 [14] 中:post = Post.objects.filter(id=1) 在 [15] 中:post.update(view_count = F('view_count') + 1) Out[15]:1 在 [16]:post[ 0].view_count Out[16]: 5 @Muthuvel 谢谢,我在更新queryset
时出错了。【参考方案3】:
你为什么不直接写post.view_count += 1
?
【讨论】:
如果我们将使用 F(),获取数据库而不是 Python 来完成工作并减少某些操作所需的查询数量参考:docs.djangoproject.com/en/1.7/ref/models/queries/#f-expressions 但既然你想真正获得价值,那么使用F
如果我们使用 F(),我们可以减少查询时间。对吗?
如果你打算拉一个项目没有区别,唯一的区别是内存,所以它对于对象的整个查询很有用,而不仅仅是一个
post.view_count = F('view_count') + 1
的优点是它会总是将值加一。如果两个用户同时执行post.view_count += 1
,则该值可能会更新 1,而不是 2。以上是关于Django DB Models F 组合表达式的主要内容,如果未能解决你的问题,请参考以下文章