有效地更新同一字段多个对象django
Posted
技术标签:
【中文标题】有效地更新同一字段多个对象django【英文标题】:Efficiently update same field multiple objects django 【发布时间】:2021-08-30 07:55:18 【问题描述】:我有一个模型,我想为多个记录发送一个将字段值增加 1 的值。 我搜索了有效的更新答案,例如Efficient way to update multiple fields of Django model object,但他们认为我有值而我想增加,因此不同记录的值可能不同。
我的模型看起来像这样:
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”
【问题讨论】:
【参考方案1】:您可以使用.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
subquery [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,
)
【讨论】:
感谢您的及时答复。这减少了我的查询数量,但有没有办法避免完全循环和更清晰的代码?也许一些固有的 django 功能可以帮助我? @ShubhamPeriwal:不是在您创建 new 对象时。如果您想更新对象,那么您可以使用.update(...)
。然而,循环不会进行任何查询,因此这通常会以每秒约 100k 次迭代运行,这可能就足够了。毕竟数据库也会做一些循环来更新记录,所以不会改变时间复杂度。
啊好的好的,谢谢。我不想更新现有的行。我需要为每条记录创建一个新行。我想循环是唯一的方法!让我试试看
Willem Van Onsem ~ 抱歉,我又添加了一项功能。是否可以更新您的代码以使用它?我无法最终实现它。
@ShubhamPeriwal 我觉得你的造型很糟糕。如果你想对这个模型进行某种版本控制,使用一个外键的额外模型会更好。以上是关于有效地更新同一字段多个对象django的主要内容,如果未能解决你的问题,请参考以下文章
如何根据记录中其他 4 个字段的布尔运算符有效地更新数据框中的字段?