Django: bulk update based on calculation

I have a Django app that shows users can vote. To simplify the task, I denormalized the data so that the photo object had the current_rating and current_rank fields. I want to update the current_rank field for all objects with every new vote, but I'm not sure how to avoid this in a loop. How to do it:

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

How is one update operation in ORM?

+4
source share
1 answer

I think you mean one transaction in the transaction manager, not one transaction per iteration.

I believe the loop design is great, but you need to manage the transaction manager.

First you need to use the Django transaction manager, which you can read about here:

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

You will need to add this line to your middleware_classes in settings.py

 'django.middleware.transaction.TransactionMiddleware', 

Then you will need to import the transaction, wherever you are,

 from django.db import transaction 

Put your loop in a function and add a decorator, for example:

 @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 

Now, when this function is called, it will have only one transaction, not N. If this fails, the transaction will be rolled back.

You can also use commit_manually. See the docs above for more details.

+7
source

Source: https://habr.com/ru/post/1399240/


All Articles