首页 > 解决方案 > 有效地更新同一字段多个对象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”

标签: pythonsql-serverdjangodjango-models

解决方案


.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,
)

推荐阅读