pythondjangopaginationdjango-pagination

How do I keep all query parameters intact when changing page in django?


I have this issue with pagination:

<a href="{{ request.get_full_path }}{% if request.GET %}&{% else %}?{% endif %}page={{ page_obj.previous_page_number }}">previous</a>

It works fine, but every time I click on it it adds one more ?page=1 at the end of the URL, so url looks like this after a few clicks: example/something?query_params=5&page=1&page=1&page=1&page=1

I know why that happens, it's because I hardcoded it into URL, but I have to use get_full_path because I need other query parameters together with page.

So basically I want all those query params but WITHOUT page=something being added each time I change the page. I need only one page query parameter.


Solution

  • You can effectively remove the page number in the view, like:

    class MyView(View):
        # …
    
        def request_get(self):
            rq = self.request.GET.copy()
            rq.pop(self.page_kwarg, None)
            return rq.urlencode()

    then in the view, we can work with:

    <a href="{{ request.path }}?{{ view.request_get }}&amp;page={{ page_obj.previous_page_number }}">previous</a>

    we can also make a helper function for this to include the path:

    class MyView(View):
        # …
    
        def request_get(self):
            rq = self.request.GET.copy()
            rq.pop(self.page_kwarg, None)
            return rq.urlencode()
    
        def path_without_page(self):
            return f'{self.request.path}?{self.request_get()}'

    and thus work with:

    <a href="{{ view.path_without_page }}&amp;page={{ page_obj.previous_page_number }}">previous</a>

    It is however a bit of a pity that the page object itself has no access to the request object, and that thus the pager could construct such links. I personally find this one of the shortcomings of Django's pagination system.