Подтвердить что ты не робот

Обновите все модели сразу в Django

Я пытаюсь обновить поле позиции для всех объектов в определенном порядке сразу в 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)

Спасибо!

4b9b3361

Ответ 1

Вы можете использовать выражение F() из django.db.models, чтобы сделать то же самое:

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

который будет генерировать один SQL-запрос для обновления всех значений столбца, поэтому он также эффективен для базы данных.

Ответ 2

Насколько мне известно, объектно-реляционная система сопоставления Django не дает возможности выразить эту операцию обновления. Но если вы знаете, как выразить это в SQL, вы можете запустить его с помощью пользовательского SQL-запроса:

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

(но это не проверено, так что будьте осторожны!).