2

I have 4 BaseReward objects, that have a default ordering of (rank, id) in Meta class. My aim is to update the objects such that I preserve their relative rankings, but give them unique ranks starting from 1,

Originally:

| id | rank |
|----|------|
| 1  | 3    |
| 2  | 2    |
| 3  | 2    |
| 4  | 1    |

after calling rerank_rewards_to_have_unique_ranks() should become

| id | rank |
|----|------|
| 1  | 4    |
| 2  | 2    |
| 3  | 3    |
| 4  | 1    |

I am trying to use F() expression with lookup .index() on list, but Django won't accept it as F() expression has only a fixed set of operators https://docs.djangoproject.com/en/1.8/topics/db/queries/#filters-can-reference-fields-on-the-model

Is there another way of achieving the same in an optimized way, without bringing the objects to database?

models.py

class BaseReward(models.Model):
    class Meta:
        ordering = ('rank', 'id')    
        # BaseReward.objects.all() gets the objects ordered by 'rank' as in the Meta class, and then by id if two objects have same rank

helper.py

def rerank_rewards_to_have_unique_ranks():

    qs = BaseReward.objects.all() # this would give the rewards of that category ordered by [rank, id]

    id_list_in_order_of_rank = list(qs.values_list('id', flat=True))        # get the ordered list of ids sequenced in order of ranks

    # now I want to update the ranks of the objects, such that rank = the desired rank

    BaseReward.objects.all().update(rank=id_list_in_order_of_rank.index(F('id'))+1)
dowjones123
  • 3,695
  • 5
  • 40
  • 83

0 Answers0