12

I use the code from the documentation to paginate the data:

try:
    data = paginator.page(request.GET.get('page'))
except PageNotAnInteger:
    page = 1
    data = paginator.page(1)
except EmptyPage:
    data = paginator.page(paginator.num_pages)

And a page:

<div class="pagination">
      <span class="step-links">
          {% if data.has_previous %}
              <a href="?page={{ data.previous_page_number }}">previous</a>
          {% endif %}

          <span class="current">
              <b>Page</b> {{ data.number }} of {{ data.paginator.num_pages }}
          </span>

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

      </span>
    </div>

But there's a bug here: when the url contains a query string and one clicks on the Pager, the original query string gets lost. For example:

example.com?var1=33&var2=44

and then when one clicks on "page2", the url becomes

example.com?page=2  # var1=33&var2=44 is lost

instead of:

example.com?var1=33&var2=44&page=2 

I haven't found neither the standard, nor easy way to fix it. How can I do that?

UPDATE:

of course, the names of the parameters, their values and whether they exist or not is not known.

udo
  • 4,832
  • 4
  • 54
  • 82
  • I used one of the two simple solutions mentioned [here](https://simpleisbetterthancomplex.com/snippet/2016/08/22/dealing-with-querystring-parameters.html). Also, its important to note that a javascript solution (as suggested in a few SO posts) may work here but may affect the SEO since page links wont be real URLs in that case – Anupam Feb 14 '18 at 06:10

4 Answers4

19

You can access parameters from your request directly in your template if you activate django.core.context_processors.request in your settings. See https://docs.djangoproject.com/en/1.7/ref/templates/api/#django-core-context-processors-request

Then you can access parameters in your template directly. In your case you'll need to filter page parameter. You could do something like this:

href="?page={{ data.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}"
Julien Grégoire
  • 16,864
  • 4
  • 32
  • 57
18

Another possible solution can be to construct parameters list in your view. Pros: you can use clean and expressive methods on QueryDict.

It will be look like this:

get_copy = request.GET.copy()
parameters = get_copy.pop('page', True) and get_copy.urlencode()
context['parameters'] = parameters

That's it! Now you can use your context variable in template:

 href="?page={{ paginator.next_page_number }}&{{ parameters }}" 

See, code looks clean and nicely.

note: assumes, that your context contained in context dict and your paginator in paginator variable

prokaktus
  • 582
  • 5
  • 12
0

The easy way would be to include those variables in your template:

<a href="?var1={{var1}}&var2={{var2}}&page={{ data.next_page_number }}">next</a>

Just add var1 and var2 to your context.

That's if the query string variables are originated from your backend. If they're coming from the front-end/external, you could use something like How can I get query string values in JavaScript? in your template and either edit the template vars directly or pass the values to your backend.

Community
  • 1
  • 1
YPCrumble
  • 26,610
  • 23
  • 107
  • 172
0

Similar to YPCrumble's answer, the following snippet works for me. But the template files could get pretty crowded when there are multiple parameters.

<a href="?p={{ page }}{% if search %}&search={{ search }}{% endif %}">{{ page }}</a>

Note that you must know the parameter names when apply this solution, so it may not fully satisfy your need.

jpch89
  • 26
  • 3