0
votes

I'm having a problem with django's for loop template tag not sorted.

{% for profile in profiles|sort_list:filter_args %}
  my code here
{% endfor %}

'profiles' is a list of dictionaries, and I'm trying to sort the list based on a chosen sort option from input on the page.

<select name="sort" id="sort" onchange="sort();">
  <option value="username">username</option>
  <option value="age">age</option>
  <option value="height">height</option>
</select>

The logic I used follows the steps.

  1. Manually change the sorting option like sort by username or sort by age, etc..
  2. Javascript detects the onchange event and send a request to the server using Ajax.
  3. The server returns the sort and reverse options like
filter_args = {'sort_by': 'username', 'up_down': 'up'}
  1. 'filter_args' goes into a custom template tag filter defined as
def sort_list(profiles, filter_args):
    sort_by = filter_args["sort_by"]
    up_down = filter_args["up_down"]
    if up_down == "down":
        profiles = sorted(profiles, key=lambda i: i[sort_by], reverse=True)
    else:
        profiles = sorted(profiles, key=lambda i: i[sort_by])
    return profiles
  1. Then, I should see that the profiles list is sorted. And HTML elements in the for loop should sorted too.
{% for profile in profiles|sort_list:filter_args %}
  my code here
{% endfor %}

I also made sure that the custom template tag works fine (put print() in the function).

def sort_list(profiles, filter_args):
    sort_by = filter_args["sort_by"]
    up_down = filter_args["up_down"]
    if up_down == "down":
        profiles = sorted(profiles, key=lambda i: i[sort_by], reverse=True)
    else:
        profiles = sorted(profiles, key=lambda i: i[sort_by])

    for x in profiles:
        print(x["username"])
    return profiles

After running, I could see that queryset is sorted as I want.
But it seems like it doesn't make any effect on for loop.

I don't see any change before and after I put the logic.
Can anybody help?

Sort your query in the view and return as context - DedicatedDreamer
I already did. I made 'my code here' part in the views and used {{ something | safe }}. But there was no change. - Asher Nagasaki
Ajax uses POST request but the server returns using render() just like normal access. I feel something wrong with this. - Asher Nagasaki
@AsherNagasaki Your html once rendered (and sent to the client) has nothing to do with the server. You are expecting that just changing filter_args on a request by ajax would change your html. You need to return some html in the response to the ajax request and use javascript to put it in the correct place. - Abdul Aziz Barkat
@AbdulAzizBarkat Thank you so much! I used HttpResponse and made Ajax put the response code to the correct place. Now it's working! - Asher Nagasaki