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 组合表达式的主要内容,如果未能解决你的问题,请参考以下文章

来自 django.db.models.Value 转换为查询字符串时不包括引号

由于没有表实例,Django不允许向DB添加记录

Django篇之F,Q

Django基础五之django模型层多表操作

使用 F 和 Q 表达式进行 Django 模型过滤

django学习之- Models笔记