Question

I've got a model in a simple django app that records a score for people entering a competition. I've got two model objects, Entry and Person. Each Entry has a Person and a Person has multiple Entries.

I want to generate a page which shows each user, their total score and their rank.

The command I've got so far is as follows:

Entry.objects.values('person__name').annotate(total=Sum('score')).order_by('-total')

I can output the result of this onto the page nicely using a for block. The only thing I don't get is the rank.

What would be the best way of adding to each record the numerical rank of the record, including the fact that when two scores are the same, the rank reflects this (ie. "4=")? Would it be better to try and do this in the template using a forblock.counter and some lookahead/behind mechanism, or to try and work this field into the query itself?

Was it helpful?

Solution

This sort of thing is very tricky. I would actually do all the work in the view, modifying the queryset there and passing it onto the template.

rank = 1
previous = None
entries = list(entries)
previous = entries[0]
previous.rank = 1
for i, entry in enumerate(entries[1:]):
    if entry.value != previous.value:
        rank = i + 2
        entry.rank = str(rank)
    else:
        entry.rank = "%s=" % rank
        previous.rank = entry.rank
    previous = entry

OTHER TIPS

Keep it simple, use the template loop.counter or loop.revcounter, don't mess with the query in this case I think.

You do not get anything more but person.name, because you specified that in values. Add total and should be ok.

Entry.objects.values('person__name', 'total').annotate(total=Sum('score')).order_by('-total')

EDIT:

Another solution:

Person.objects.values('name').annotate(total=Sum('entries__score')).order_by('-total')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top