Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ListView pagination using get_queryset

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!

like image 750
JohnJ Avatar asked Feb 19 '13 14:02

JohnJ


1 Answers

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 %}
like image 65
almalki Avatar answered Sep 28 '22 06:09

almalki