Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pagination and get parameters

Tags:

django

Django 1.11.4

I have build a search form with method="get". Search form has a lot of forms. Then this input values are transmitted as get parameters in url.

The problem is how to get pagination. The database contains thousands of objects. Pagination is necessary.

This is what the documentation tells us:

https://docs.djangoproject.com/en/1.11/topics/pagination/#using-paginator-in-a-view

It suggests like this:

<a href="?page={{ contacts.previous_page_number }}">previous</a>

But this will ruin all the get parameters.

What I have managed to invent is:

<a href="{{ request.get_full_path }}&page={{ object_list.previous_page_number }}">previous</a>

This works. But this is goofy. If one switches pages forward and backward, it produces urls ending like this:

page=2&page=3&page=2

I have had a look at how Google managed this problem. In the middle of the url they have start=30. And change this parameter: start=20, start=40. So, they switch.

Could you help me understand how preserve get parameters and switch pages in Django? In an elegant way, of course.

like image 955
Michael Avatar asked Sep 03 '17 17:09

Michael


People also ask

Does pagination improve performance?

Thanks to pagination, we can split our large dataset into chunks ( or pages ) that we can gradually fetch and display to the user, thus reducing the load on the database. Pagination also solves a lot of performance issues both on the client and server-side!

Can we do pagination for data in rest framework?

REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.

What is REST API pagination?

You can paginate the JSON response that is called from the REST API. The order of the data is retained from page to page. Given the ability to paginate, you can quickly populate tables and make new REST calls every time you go to the next page of the data on the table.


2 Answers

The generic solution is to define a "custom template tag" (a function) which keeps the complete URL but updates the GET parameters you pass to it.

After registration, you can use this function in your templates:

<a href="?{% query_transform page=contacts.previous_page_number %}">previous</a>

To define and register the custom template tag, include this code in a python file:

from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
def query_transform(context, **kwargs):
    query = context['request'].GET.copy()
    for k, v in kwargs.items():
        query[k] = v
    return query.urlencode()

*Thanks to Ben for the query_transform code. This is an adapation for python 3 from his code.

Why this method is better than reconstructing the URLs manually:

If you later decide that you need additional parameters in your URLs: 1. you don't have to update all the links in your templates. 2. You don't need to pass all the params required for recostructing the URL to the templates.

like image 200
addmoss Avatar answered Oct 23 '22 18:10

addmoss


Typically, to preserve GET parameters you simply re-write them manually. There shouldn't be many cases where having to do this will matter.

&page={{page}}&total={{total}}

You can abstract this away into a template include or a custom template tag.

https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/

Additionally, you could create a string filter that takes URL params as a string as well as a dict of values you want to change. The filter could then parse the params string, update the value, then recombine the string back into URL params.

{{ request.get_full_path | update_param:'page=8' }}
like image 32
Soviut Avatar answered Oct 23 '22 18:10

Soviut