在 Django 中一次更新所有模型

Posted

技术标签:

【中文标题】在 Django 中一次更新所有模型【英文标题】:Update all models at once in Django 【发布时间】:2013-03-20 14:46:33 【问题描述】:

我正在尝试在 Django (python) 中以特定顺序一次更新所有对象的位置字段。

我现在就是这样做的,但问题是它会产生大量查询。

    servers = frontend_models.Server.objects.all().order_by('-vote_count')

    i = 1
    for server in servers:
        server.last_rank = i
        server.save()
        i += 1

有没有办法更新

Model.objects.all().order_by('some_field').update(position=some_number_that_changes_for each_object)

谢谢!

【问题讨论】:

您想为每个对象增加传递的数字吗? django 查询 api 没有 windows functions (我认为)。如果您的 RDBMS 具有此功能,您应该执行 custom sql directly。 【参考方案1】:

您可以使用django.db.models 中的F() 表达式来做同样的事情:

Model.objects.all().order_by('some_field').update(position=F(some_field)+1)

这将生成单个 SQL 查询来更新所有列值,因此对数据库也很有效。

【讨论】:

这并不能回答 OP 的问题,因为 F() 只能根据同一行中字段的值进行计算,而不是根据需要跨行递增。 对于具体陈述的问题,也可以重构为在同一行上工作;没有? 这只有在我可以使用 F(same_field_of_previous_row) + 1 的前一行时才有效 “F() 的实例充当对查询中模型字段的引用。这些引用可以在查询过滤器中使用,以比较同一模型实例上两个不同字段的值。”因此,这不会完成 OP 需要做的事情。 此外,我们应该在 F('some_field') 中加上一些引号,以便真正明确。【参考方案2】:

据我所知,Django 的对象关系映射系统并没有提供表达这种更新操作的方法。但是如果你知道如何用 SQL 来表达,那么你可以通过custom SQL query 运行它:

from django.db import connection
cursor = connection.cursor()
cursor.execute('''UPDATE myapp_server ...''')

不同的数据库引擎以不同的方式表达此操作。在 mysql 中,您将运行以下查询:

SET @rownum=0;
UPDATE myapp_server A,
       (SELECT id, @rownum := @rownum + 1 AS rank
        FROM myapp_server
        ORDER BY vote_count DESCENDING) B
SET A.rank = B.rank
WHERE A.id = B.id

在 PostgreSQL 中我认为你会使用

UPDATE myapp_server A,
       (SELECT id, rownumber() AS rank
        OVER (ORDER BY vote_count DESCENDING)
        FROM myapp_server) B
SET A.rank = B.rank
WHERE A.id = B.id

(但这是未经测试的,所以要小心!)。

【讨论】:

以上是关于在 Django 中一次更新所有模型的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 中一次提交中执行多个 save() 的最佳方法

Django:渲染视图后如何更新模型?

Django(16)模型的操作(增删改查)

尝试在 mvc 3 中一次将两个模型传递到同一个视图时出现问题

仅更新该属性而不是所有模型,django

如何在不在 python 中迭代它们的情况下明显地批量更新 django 模型的所有对象?