Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ListView - Form to filter and sort

Tags:

My Goal

  • A site that list all my Updates (model) in a table
  • Dont display all models at once (pagination - maybe 10 per page)
  • Filter and sort the list

My thoughts

  • I can use ListView to get a set of all my Updates
  • Use paginate_by = 10
  • Use a form to set order_by or filter in my QuerySet

My Problem

I am not sure how to add an form to modify my QuerySet with filter and sortings. My Idea was to modify the Query in get_queryset with additional filter and order_by.

My View

class MyView(ListView):     model = Update     template_name = "updates/update.html"     paginate_by = 10      def get_queryset(self):         return Update.objects.filter(             ~Q(state=Update.STATE_REJECTED),             ~Q(state=Update.STATE_CANCELED),             ~Q(state=Update.STATE_FINISHED),         ).order_by(             'planned_release_date'         ) 

My Idea

Something like this. I know it's not working like this ... just to illustrate

class MyView(ListView):     model = Update     template_name = "updates/update.html"     paginate_by = 10      def post(self, request, *args, **kwargs):         new_context = Update.objects.filter(             request.POST.get("filter"),         ).order_by(             request.POST.get("sorting"),         )      def get_queryset(self):         return Update.objects.filter(             ~Q(state=Update.STATE_REJECTED),             ~Q(state=Update.STATE_CANCELED),             ~Q(state=Update.STATE_FINISHED),         ).order_by(             'planned_release_date'         ) 
like image 554
Rooterle Avatar asked Oct 26 '15 16:10

Rooterle


2 Answers

You don't need post. Pass the filter value and order_by in the url for example:

.../update/list/?filter=filter-val&orderby=order-val

and get the filter and orderby in the get_queryset like:

class MyView(ListView):     model = Update     template_name = "updates/update.html"     paginate_by = 10      def get_queryset(self):         filter_val = self.request.GET.get('filter', 'give-default-value')         order = self.request.GET.get('orderby', 'give-default-value')         new_context = Update.objects.filter(             state=filter_val,         ).order_by(order)         return new_context      def get_context_data(self, **kwargs):         context = super(MyView, self).get_context_data(**kwargs)         context['filter'] = self.request.GET.get('filter', 'give-default-value')         context['orderby'] = self.request.GET.get('orderby', 'give-default-value')         return context 

Make sure you give proper default value to filter and orderby

Example form (you can modify this to your need):

<form method="get" action="{% url 'update-list' %}">     <p>Filter: <input type="text" value={{filter}} name="filter"/></p>     <p>order_by: <input type="text" value={{orderby}} name="orderby"/></p>     <p><input type="submit" name="submit" value="submit"/></p> </form> 
like image 53
Anush Devendra Avatar answered Oct 15 '22 04:10

Anush Devendra


I am wondering why nobody mentioned here this cool library: django-filter https://github.com/carltongibson/django-filter

you can define your logic for filtering very clean and get fast working forms etc.

demo here: https://stackoverflow.com/a/46492378/953553

like image 30
andilabs Avatar answered Oct 15 '22 06:10

andilabs