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.
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!
REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.
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.
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.
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' }}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With