python - 有效地更新同一字段多个对象django
问题描述
我有一个模型,我想将多个记录的字段值增加 1。我搜索了有效的更新答案,例如更新 Django 模型对象的多个字段的有效方法,但他们假设我有值,而我想增加,因此不同记录的值可能不同。
我的模型看起来像这样:
class Signal(models.Model):
name = models.CharField(max_length=80)
version = models.IntegerField()
在我看来,我想发送一个名称列表,然后将其所有版本更新 1。
我目前的方法是查看名称、创建对象、更新版本并手动保存,如下所示:
signals = Signal.objects.filter(name__in=signal_names)
for signal in signals:
signal.pk=None
signal.version = signal.version+1
signal.save()
这会导致查询过多并且非常慢,因为我将一次发送 100 个名称。
有一个更好的方法吗?
注意:这可能看起来类似于批量更新问题,但在这种情况下,我想增加 1,所以我没有更新的值。那是我与现有答案的斗争。
例子:
信号表
name | version
n1 | 1
n2 | 2
我在我的帖子中发送 ["n1", "n2"] 并且输出应该是
信号表
name | version
n1 | 1
n2 | 2
n1 | 2
n2 | 3
更新 我发现的另一个意外情况是,下次我想更新时,我只想更新最新版本——不是全部
所以如果我再次运行 POST 请求,值应该是
信号表
name | version
n1 | 1
n2 | 2
n1 | 2
n2 | 3
n1 | 3
n2 | 4
如何过滤以仅更新每个名称的最新版本?我使用的数据库是“sql server”
解决方案
.bulk_create(…)
您可以使用[Django-doc]制作新信号列表并在数据库中批量创建这些信号:
# create new Signal objects
results = []
signals = Signal.objects.filter(name__in=signal_names)
for signal in signals:
signal.pk = None
signal.version += 1
results.append(signal)
Signal.objects.bulk_create(results)
然而,这会产生重复。如果你想更新现有 Signal
的 s,那么你可以使用.update(…)
[Django-doc]:
# updating the existing the Signal objects
signals = Signal.objects.filter(name__in=signal_names).update(
version=F('version') + 1
)
如果您只想获取最新版本,则应signals
使用Exists
子查询 [Django-doc]更改查询集:
from django.db.models import Exists, OuterRef
Signal.objects.filter(
~Exists(Signal.objects.filter(
name=OuterRef('name'), version__gt=OuterRef('version')
)),
name__in=signal_names,
)