Using both sort & filter on a QuerySet

拥有回忆 提交于 2019-12-23 02:45:11

问题


I have a list of userprofiles that I want to be able to sort and filter.

I have been able to do this manually, by manually typing in the URLs, but I haven't been able to code the template page to allow the persistence of a previously-applied filter or sort. Here is the url and template code that I currently have --

# in urls
url(r'^talent/filter\:(?P<position>[A-Za-z]+)/sort\:(?P<sort>[A-Za-z]+)$', 'talent_filter', name='talent_filter_sort'),
url(r'^talent/filter\:(?P<position>[A-Za-z]+)/$', 'talent_filter', name='talent_filter'),
url(r'^talent/sort\:(?P<sort>[A-Za-z]+)/$', 'talent_sort', name='talent_sort'),
url(r'^talent/$', 'talent', name='talent'),

# in template
<ul>
    <li>SORT BY:</li>
    <li><a href = "{% url talent_sort sort='alphabetical'%}">Alphabetical</a></li>
    ...
</ul>
<ul>
    <li><a href = '{% url talent_filter position=position%}'>{{ position }}</a></li>
    ... 
</ul>

Currently, if I am on the (unsorted, unfiltered) talent page, and I select a filter on the results, it will return talent/filter:filter. Then, if I choose to sort the results, it (obviously) goes to talent/sort:sort, removing the previous filter.

What I want to accomplish is that if I am currently on talent/filter:filter and click a sort method, it will go to talent/filter:filter/sort:sort, and if I have already sorted the results (talent/sort:sort) and click on filter, it will also take me to talent/filter:filter/sort:sort. How would I accomplish this. Thank you.


回答1:


I think one way you might be able to accomplish this is store a flag in your session that indicates what the sorting or filtering should be. For example, something like below could be used to save the state of the your sort choice.

request.session['TALANT_SORT'] = "alphabetical"
request.session['TALENT_FILTER'] = "top_ten" 

And then your views can check for the existence the session keys and apply a filter accordingly.

qs = models.MyModel.objects.all()

sort = request.session.get('TALENT_SORT', None)
if sort in ["alphabetical", "created_date"]:
    qs = qs.order_by(sort)

myfilter = request.session.get("TALENT_FILTER", None)
if myfilter in ["top_ten","bottom_ten"]:
    qs = qs.filter( .... ) 

....

The sorting and filtering could then persist across requests.

If you want to remove the sort or filter, then perhaps you can delete the session keys in the view depending on some user action:

try:
    del request.session['TALENT_SORT']
    del request.session['TALENT_FILTER']
except KeyError: 
    pass 

Also, depending on your requirements, you might consider combining the 2 urls into 1 and just use GET parameters to activate the sort.

request.GET.get('sort',None)
....
request.GET.get('filter', None)
....

These examples could probably use some more rigor, but that's the idea. Hope this helps. Joe




回答2:


Despite being slightly against what django is all about, the best approach to user specified sorts/filters if to use GET variables. So your URLs would appear like:

/talent/?filter=foo&sort=bar

Within your view set context variables for your current filter and sort then use those to build your urls in your templates.

Something like: Alphabetical

If you really feel it's necessary to use url captured parameters you'll need to set up your urls to handle all the conditions (sort set, filter set, neither set, and both set). And then in your templates you'll need a bunch of if statements to select the correct url and parameters.

As I said this type of situation is much better handled with GET parameters.



来源:https://stackoverflow.com/questions/6379841/using-both-sort-filter-on-a-queryset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!