How to paginate Django with other get variables?

vagabond picture vagabond · Jan 12, 2010 · Viewed 28.6k times · Source

I am having problems using pagination in Django. Take the URL below as an example:

http://127.0.0.1:8000/users/?sort=first_name

On this page I sort a list of users by their first_name. Without a sort GET variable it defaults to sort by id.

Now if I click the next link I expect the following URL:

http://127.0.0.1:8000/users/?sort=first_name&page=2

Instead I lose all get variables and end up with

http://127.0.0.1:8000/users/?page=2

This is a problem because the second page is sorted by id instead of first_name.

If I use request.get_full_path I will eventually end up with an ugly URL:

http://127.0.0.1:8000/users/?sort=first_name&page=2&page=3&page=4

What is the solution? Is there a way to access the GET variables on the template and replace the value for the page?

I am using pagination as described in Django's documentation and my preference is to keep using it. The template code I am using is similar to this:

{% if contacts.has_next %}
    <a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}

Answer

mpaf picture mpaf · May 17, 2013

I thought the custom tags proposed were too complex, this is what I did in the template:

<a href="?{% url_replace request 'page' paginator.next_page_number %}">

And the tag function:

@register.simple_tag
def url_replace(request, field, value):

    dict_ = request.GET.copy()

    dict_[field] = value

    return dict_.urlencode()

If the url_param is not yet in the url, it will be added with value. If it is already there, it will be replaced by the new value. This is a simple solution the suits me, but does not work when the url has multiple parameters with the same name.

You also need the RequestContext request instance to be provided to your template from your view. More info here:

http://lincolnloop.com/blog/2008/may/10/getting-requestcontext-your-templates/