我想使用 Django 根据其当前值将字段更新为不同的值,但我不知道如何在不执行 2 个单独的更新语句的情况下执行此操作。
这是我想做的一个例子:
now = timezone.now()
data = MyData.objects.get(pk=dataID)
if data.targetTime < now:
data.targetTime = now + timedelta(days=XX)
else:
data.targetTime = data.targetTime + timedelta(days=XX)
data.save()
Run Code Online (Sandbox Code Playgroud)
现在,我想使用 update() 语句来避免覆盖数据上的其他字段,但我不知道如何在单个 update() 中执行此操作。我尝试了一些这样的代码,但第二次更新没有使用最新时间(我最终得到了一个等于当前时间的字段):
# Update the time to the current time
now = timezone.now()
MyData.objects.filter(pk=dataID).filter(targetTime__lt=now).update(targetTime=now)
# Then add the additional time
MyData.objects.filter(pk=dataID).update(targetTime=F('targetTime') + timedelta(days=XX))
Run Code Online (Sandbox Code Playgroud)
有没有办法可以将其简化为单个 update() 语句?类似于 SQL CASE 语句的东西?
你需要使用条件表达式,像这样
from django.db.models import Case, When, F
object = MyData.objects.get(pk=dataID)
now = timezone.now()
object.targetTime = Case(
When(targetTime__lt=now, then=now + timedelta(days=XX)),
default=F('targetTime') + timedelta(days=XX)
)
object.save(update_fields=['targetTime'])
Run Code Online (Sandbox Code Playgroud)
对于调试,请尝试立即运行此命令save以查看刚刚运行的 SQL 查询:
import pprint
from django.db import connection
pprint.pprint(["queries", connection.queries])
Run Code Online (Sandbox Code Playgroud)
我已经用整数测试过它并且它在 Django 1.8 中工作,我还没有尝试过日期,所以它可能需要一些调整。
Django 1.9 添加了 Greatest 和 Least数据库函数。这是Benjamin Toueg回答的改编版:
from django.db.models import F
from django.db.models.functions import Greatest
MyData.objects.filter(pk=dataID).update(
targetTime=Greatest(F('targetTime'), timezone.now()) + timedelta(days=XX)
)
Run Code Online (Sandbox Code Playgroud)
Django 3 及以上版本的简单示例:
from django.db.models import Case, Value, When, F
MyModel.objects.filter(abc__id=abc_id_list)\
.update(status=Case(
When(xyz__isnull=False, then=Value("this_value")),
default=Value("default_value"),))
Run Code Online (Sandbox Code Playgroud)
如果我理解正确的话,你需要从现在到数据库中的值之间的最长时间。
如果是这样,您可以使用 max 函数在一行中完成此操作:
from django.db.models import F
MyData.objects.filter(pk=dataID).update(targetTime=max(F('targetTime'),timezone.now()) + timedelta(days=XX))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7693 次 |
| 最近记录: |