Django ListView pagination using get_queryset

django, django-models, django-templates, django-views

Solution

Query parameters must be separated by & not /

/search/?q={{searchq}}/page={{ page_obj.previous_page_number }}

should be:

/search/?q={{searchq}}&page={{ page_obj.previous_page_number }}

Also, it is best practice to use URL resolver instead of hard-coding the url, something like:

{% url 'search' searchq page_obj.previous_page_number %}

Problem

I have been trying to learn and get to grips with ListViews with pagination in Django, but I seem to be having some trouble in understanding concepts. So, let me show some code - my view.py looks something like this: ``` class SearchDisplayListView(ListView): model = BlogPosts template_name = "searchres_list.html" paginate_by = '15' context_object_name = "searchres" def get_context_data(self, **kwargs): context = super(SearchDisplayListView, self).get_context_data(**kwargs) q = self.request.GET.get('q') q = q.replace(" ","+") context['searchq'] = q return context def get_queryset(self): queryset = super(SearchDisplayListView, self).get_queryset() # Get the q GET parameter q = self.request.GET.get('q') q = q.replace(" ","+") if q is None: # Return the base queryset return queryset # Return a filtered queryset ## do some awesome calculations using "q" i.e send request to search server ## get back a list from the search server.. example: range(0,100) queryset = range(0,100) return queryset ``` As you can see, I do not actually populate my queryset using Models - but rather from my own "search server" which returns me results - say in this example range(0,100). Now, I am trying to use the following in my template code: ``` <table class="table table-hover"> <tbody> {% for i in searchres %} <tr> <td><img src="http://placehold.it/140x140" class="img-polaroid"></td> <td>{{i}}</td> </tr> {% endfor %} </tbody> </table> ``` and my pagination looks as follows: ``` {% if is_paginated %} <div class="pagination pagination-centered"> <ul> {% if page_obj.has_previous %} <li><a href="/search/?q={{searchq}}/page={{ page_obj.previous_page_number }}">Prev</a></li> {% endif %} {% for i in paginator.page_range %} {% if page_obj.has_next %} <li><a href="/search/?q={{searchq}}/page={{ page_obj.number }}">{{i}}</a></li> {% endif %} {% endfor %} {% if page_obj.has_next %} <li><a href="/search/?q={{searchq}}/page={{ page_obj.next_page_number }}">Next</a></li> {% endif %} </ul> </div> ``` Now, I have the following problems: [1] Although the template seems to paginate the first set (i.e 0 to 14), I am not able to see the other values in the subsequent pages. So, when I click on next page, I get: ``` - http://mydata:8000/search/?q=myquery/page=2 ``` and when I click next page again, I get: ``` - http://mydata:8000/search/?q=boots/page=2/page=2 ``` which is obviously wrong. I am not able to see how I can generate: ``` - http://mydata:8000/search/?q=boots/page=3 ``` [2] Even when I manually set: ``` - http://mydata:8000/search/?q=boots/page=3 ``` I see values again from 0 to 14 rather than the logical set in page:3. Also, this basically tells me that on each page, the get_queryset seems to run, generating the first 0 to 14 values - which is not what I want. As you can see, I have my own custom data set in get_queryset - rather than any DB interaction - so, I am unsure how I can paginate this custom data. Thanks for your time reading my rather long post!

Original source