python - 使用 F 表达式保存两次
问题描述
执行以下代码时。
from django.db.models import F
# assume that stories_filed is 0 at the start.
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
reporter.save()
结果是stories_filed
等于2
。为什么会这样,有没有避免这个错误的好方法。将其包装在事务中会防止该问题吗?
解决方案
F
表达式 [Django-doc]是对字段的引用。如果您设置stories_filed
为F('stories_filed') + 1
,那么当您设置为 时.save()
,它将进行如下查询:
UPDATE app_reporter
SET stories_filed = stories_filed + 1
WHERE pk = pk-of-object
因此它将增加数据库端的字段。事实上,如果你查询什么reporter.stories_filed
是,它会指定这是F('stories_filed') + 1
,所以增量逻辑不会在 Django/Python 级别执行。
请注意,如果您.save()
是一个对象,则该对象不会从数据库中重新加载,因此在第一次之后.save()
,stories_filed
仍然是F('stories_filed') + 1
,因此第二次.save()
调用将查询另一个增量。
但是,建议对F
对象执行此操作,因为存在多个视图更新同一记录的竞争条件,这可能意味着某些增量丢失。事实上,如果两个视图都适用:
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()
那么有可能在两个视图结束后,该值只增加一次,那是因为它们首先加载相同的记录,它们都将它增加一个,然后它们都保存新值,但是第二个视图将因此保存记录stories_filed
从它检索到的记录中递增,并且不考虑其他视图的更新。
推荐阅读
- python - Python获取最新文件列表并将其与旧文件列表进行比较
- python - QVD 文件到 pandas DataFrame
- python - 在 Django REST 框架中保存数据时,Id 字段显示为空
- windows - runnerw.exe:CreateProcess 失败并出现错误 5:访问被拒绝
- python - 如何在 Windows 电脑上最大化 RTSP 流
- css - CSS Transitions and animations not working
- php - 在 Laravel 8 中使用 SendGrid 发送电子邮件
- python - 如何访问在类的方法中定义的变量?
- docker - 带有反应的docker nginx服务器的CORS错误 - axios
- html - 如何将要点设置在文本顶部?