growse
growse

Reputation: 3752

Simple ranking of queryset in django template

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?

Upvotes: 4

Views: 2688

Answers (3)

stephane k.
stephane k.

Reputation: 1788

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

Upvotes: 1

Ski
Ski

Reputation: 14487

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')

Upvotes: -1

Daniel Roseman
Daniel Roseman

Reputation: 599580

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

Upvotes: 7

Related Questions