1

i'm a rookie in programming and i ran into a problem in django.

So i'm trying to sort a dictionary based on the value. I've tryed several methods seen here, but thing is nothing works for me. It worked to make the dictionary but i don't know why it's not sorting.

So 'scoruri' is the dictionary: when using it in html it's showing like this {User: alex_py: 6, User: ion: 3, User: lil: 1, User: sss: 1, User: ddd: 1, User: bbb: 7}, 'result' is the score for each 'user'(key). When i'm printing the type of scoruri it prints 6 times (type 'dict')

It may be possible that each key:value in scoruri to be actually a dictionary so i'm having a dictionary of dictionaries?

Below are the methods i've tryed to sort.

views.py

def home(request):
    data = dict()
    data['users'] = User.objects.all()
    data['scoruri'] = dict()

    if request.method == "POST":
        for key in request.POST:
            if 'nota_' in key:
                nota_acordata = Punctaj.objects.filter(acordat_de=request.user,
                                                       acordat_catre__id=key.split('_')[1]).first()
                if nota_acordata:
                    nota_acordata.nota = request.POST.get(key)
                    nota_acordata.save()

                else:
                    Punctaj.objects.create(acordat_de=request.user,
                                           acordat_catre_id=key.split('_')[1],
                                           nota=request.POST.get(key))  

                    messages.success(request, "Successfully Voted")
        return redirect('home')

    for user in data['users']:
        suma = Punctaj.objects.filter(acordat_catre=user).aggregate(punctaj=Sum('nota')).get("punctaj")
        count = Punctaj.objects.filter(acordat_catre=user).count()
        if not suma:
            result = 0
        else:
            result = int(suma)/count
        data['scoruri'][user] = result

        # sorted(data['scoruri'].items())
        # rezultate = sorted(data['scoruri'].items(), key=operator.itemgetter(1))
        print(type(data['scoruri']))
    return render(request, "login/home.html", data)

template

{{ scoruri }}
<!--{{ rezultate }}-->

<!--{% for key, value in scoruri %}-->

       <!--{{ key }}:{{ value }}-->

<!--{% endfor %}-->
alex
  • 2,381
  • 4
  • 23
  • 49
  • Some time in december Python 3.6 will be released, which has dictionaries that are always sorted by default! – RemcoGerlich Nov 17 '16 at 09:12
  • Possible duplicate of [Sort a Python dictionary by value](http://stackoverflow.com/questions/613183/sort-a-python-dictionary-by-value) – Sardorbek Imomaliev Nov 17 '16 at 09:16
  • hi, i've tryed that: it's commented rezultate = sorted(data['scoruri'].items(), key=operator.itemgetter(1)), when i use {{ rezultate }} in my template, it won't show anything. – alex Nov 17 '16 at 09:42

2 Answers2

3

You should use OrderedDict which preserves insertion order instead of dict. https://docs.python.org/2/library/collections.html

from collections import OrderedDict

def home(request):
    data = dict()
    data['users'] = User.objects.all()
    data['scoruri'] = dict()

    if request.method == "POST":
        for key in request.POST:
            if 'nota_' in key:
                nota_acordata = Punctaj.objects.filter(acordat_de=request.user,
                                                       acordat_catre__id=key.split('_')[1]).first()
                if nota_acordata:
                    nota_acordata.nota = request.POST.get(key)
                    nota_acordata.save()

                else:
                    Punctaj.objects.create(acordat_de=request.user,
                                           acordat_catre_id=key.split('_')[1],
                                           nota=request.POST.get(key))  

                    messages.success(request, "Successfully Voted")
        return redirect('home')

    for user in data['users']:
        suma = Punctaj.objects.filter(acordat_catre=user).aggregate(punctaj=Sum('nota')).get("punctaj")
        count = Punctaj.objects.filter(acordat_catre=user).count()
        if not suma:
            result = 0
        else:
            result = int(suma)/count
        data['scoruri'][user] = result

        # sorted(data['scoruri'].items())
        # sorting and puting result into OrderedDict
        data['scoruri'] = OrderedDict(sorted(data['scoruri'].items(), key=operator.itemgetter(1)))
        print(type(data['scoruri']))

    return render(request, "login/home.html", data)

And in template

{% for key, value in scoruri.items %}
    {{ key }}:{{ value }}
{% endfor %}
Sardorbek Imomaliev
  • 14,861
  • 2
  • 51
  • 63
  • well i don't really need this, i've red about it, i just want to order the dictionary by the score each user has, that's all. – alex Nov 17 '16 at 09:40
  • ok, so now if i'm doing it like you, i'll get error for 'int' object has no attribute 'rate', after that i tryed without it: OrderedDict(sorted(data['scoruri'].items(), key=lambda i: i[1])) and it worked, it ordered them, but the output was exactly this: OrderedDict([(, 1), (, 1), (, 1), (, 3), (, 6), (, 7)]), if i get OrderedDict out of the code it will give me this: list indices must be integers, not User, so it's ordering them but it outputs OrderedDict there aswell – alex Nov 17 '16 at 09:51
  • @NitaAlexandru sorry. fixed should be `data['scoruri'] = OrderedDict(sorted(data['scoruri'].items(), key=lambda i: i[1]))` or `data['scoruri'] = OrderedDict(sorted(data['scoruri'].items(), key=operator.itemgetter(1)))` – Sardorbek Imomaliev Nov 17 '16 at 09:53
  • hm... either way i'm doing it, it will show like this: [link](http://imgur.com/a/2cbow) – alex Nov 17 '16 at 10:00
  • @NitaAlexandru did read part about updating template. Reread my answer – Sardorbek Imomaliev Nov 17 '16 at 10:01
2

You can't sort a dictionary, you can sort representation of a dictionary. Dictionary has a random ordered members.

You can make list of tuples from a dict members:

import operator
dict = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_dict = sorted(dict.items(), key=operator.itemgetter(1))

I hope this helps.

Ilko
  • 1,288
  • 1
  • 14
  • 19
  • If i'm doing this: sorted_dict = sorted(data['scoruri'].items(), key=operator.itemgetter(1)) and use {{ sorted_dict }} in html, it's not showing anything. – alex Nov 17 '16 at 09:19