The most important part here is the how you construct your URLs in the template.
you probably have
{% if pages.has_previous %}
<li><a href="?page={{ pages.previous_page_number }}">Prev</a></li>
{% endif %}
which is perfectly fine if you are using only it for switching between the initial paginated results.
But the tricky part is when you use the django-fitler
filters, the querystring (that part after the '?') gets totally new key-values pairs, disregarding your ?page=2
or similar.
So to make pagination work with filtered results, when you click the "Next" or "Prev" button - among the key-values from django-fitler
you also need to pass the &page=5
as pair.
As @stathoula mentioned, you need to check if at least one of your filter fields is already present in the querystring. If it is, then you need to use the already present key-value pairs, followed by the new &page=3
pair.
It seems very simple, but I had to done small hackish not to repeat the &page=1
over and over again within the querystring as a user is clicking trough the arrows.
In my case I'm having 'title' as a filter, so I need to check if it's already present there.
Here's a snippet of what I've made working perfectly fine for my project.
templates/pagination.html
<div class="paginator">
{% with request.get_full_path as querystring %}
<ul class="pagination nav navbar-nav">
<!-- Previous page section -->
{% if pages.has_previous %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ pages.previous_page_number }}">Prev</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ pages.previous_page_number }}">Prev</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ pages.previous_page_number }}">Prev</a>
</li>
{% endif %}
{% endif %}
<!-- All pages section -->
{% for page in pages.paginator.page_range %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ page }}">{{ page }}</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ page }}">{{ page }}</a>
</li>
{% endif %}
{% endfor %}
<!-- Next page section -->
{% if pages.has_next %}
{% if 'title' in querystring %}
{% if 'page' in querystring %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring|slice:":-7" }}&page={{ pages.next_page_number }}">Next</a>
</li>
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="{{ querystring }}&page={{ pages.next_page_number }}">Next</a>
</li>
{% endif %}
{% else %}
<li class="paginator {% if pages.number == page %}active{% endif %}">
<a href="?page={{ pages.next_page_number }}">Next</a>
</li>
{% endif %}
{% endif %}
</ul>
{% endwith %}
</div>
Here is the view, just in case:
app/views.py
def index(request):
condo_list = Condo.objects.all().order_by('-timestamp_created')
condo_filter = CondoFilter(request.GET, queryset=condo_list)
paginator = Paginator(condo_filter.qs, MAX_CONDOS_PER_PAGE)
page = request.GET.get('page')
try:
condos = paginator.page(page)
except PageNotAnInteger:
condos = paginator.page(1)
except EmptyPage:
condos = paginator.page(paginator.num_pages)
return render(request, 'app/index.html', {
'title': 'Home',
'condos': condos,
'page': page,
'condo_filter': condo_filter,
})
Here's a working example:
.