Джанго: массовое обновление на основе расчета - PullRequest
4 голосов
/ 01 марта 2012

У меня есть приложение Django, которое показывает фотографии, за которые пользователи могут голосовать.Чтобы упростить задачу, я денормализовал данные, чтобы у объекта фотографии были поля current_rating и current_rank.Я хочу обновить поле current_rank на всех объектах при каждом голосовании, но я не уверен, как избежать этого в цикле.Как я могу сделать:

i = 1
for p in Photo.objects.order_by("-current_rating"):
    p.current_rank = i
    p.save()
    i += 1

как одну операцию обновления в ORM?

1 Ответ

7 голосов
/ 01 марта 2012

Я думаю, что вы имеете в виду одну транзакцию в менеджере транзакций, а не одну транзакцию на итерацию.

Я считаю, что конструкция цикла хороша, но вам нужно управлять менеджером транзакций.

Во-первых, вам нужно использовать менеджер транзакций Django, о котором вы можете прочитать здесь:

https://docs.djangoproject.com/en/dev/topics/db/transactions/

Вам нужно будет добавить эту строку в ваши middleware_classes в настройках.py

'django.middleware.transaction.TransactionMiddleware',

Затем вам нужно будет импортировать транзакцию, где бы ни находилась ваша вышеуказанная функция;

from django.db import transaction

Поместите ваш цикл в функцию и добавьте декоратор, например, так:

@transaction.commit_on_success
def my_function():
    i = 1
    for p in Photo.objects.order_by("-current_rating"):
        p.current_rank = i
        p.save()
    i += 1

Теперь, когда эта функция вызывается, у нее будет только одна транзакция, а не N. Если она не удастся, транзакция откатывается.

Вы также можете использовать commit_manually.См. Документы выше для более подробной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...