I´m having a problem when using pagination in generic ListView, when trying to filter queryset. The filter works fine, but the thing is when trying to access a page that isn´t the first,an error appears: Invalid page (2): That page contains no results
What if I remove all the pagination? What would you recommend? The goal of the template is to show date filtered sales in a list and also a client filter
This is my code:
class ListSales(LoginRequiredMixin, ListView):
template_name = "sales/list.html"
context_object_name = 'sales'
login_url = reverse_lazy('users_app:user-login')
paginate_by = 5
def get_queryset(self):
client = self.request.GET.get("clientselect", "")
date1 = self.request.GET.get("date1", '')
date2 = self.request.GET.get("date2", '')
if date1 == '':
date1 = datetime.date.today()
if date2 == '':
date2 = datetime.date.today()
queryset = Sale.objects.get_sales_list(date1, date2, client)
return queryset
And this my template:
{% extends "panel.html" %}
{% load static %}
{% block panel-content %}
<div class="grid-x medium-10">
<h3 class="cell medium-12" style="text-align: center;">Ventas</h3>
<div class="cell medium-12">  </div>
<form class="cell medium-10" method="GET">{% csrf_token %}
<div class="input-group grid-x medium-12">
<div class="input-group cell medium-3 grid-x">
<label class="cell medium-12">Desde:</label>
<span class="input-group-label"><i class="fi-calendar"></i></span>
<input type="date" id="date1" name="date1" class="input-group-field" type="date">
</div>
   
<div class="input-group cell medium-3 grid-x">
<label class="cell medium-12">Hasta:</label>
<span class="input-group-label"><i class="fi-calendar"></i></span>
<input type="date" id="date2" name="date2" class="input-group-field" type="date">
</div>
<div class="cell medium-1"></div>
<div class="input-group cell medium-3 grid-x">
<label class="cell medium-12">Cliente:</label>
<span class="input-group-label"><i class="fi-torso"></i></span>
<select id="clientselect" name="clientselect" class="input-group-field">
<option value="0" id="option0" name="option0" >Todos</option>
<option value="-1" id="option-1" name="option-1" >Sin Cliente</option>
{% for client in clients %}
<option value="{{client.pk}}" id="option{{client.pk}}" name="option{{client.pk}}" >{{client.full_name}}</option>
{% endfor %}
</select>
</div>
<div class="cell medium-1"></div>
<div class="cell medium-1">
<button type="submit" class="button cell medium-4"><i class="fi-filter"></i>  Filtrar</button>
</div>
</div>
</form>
<div class="cell medium-12"> </div>
<table class="cell medium-12">
<thead>
<th>Fecha</th>
<th>Nro Factura</th>
<th>Cliente</a></th>
<th>Monto</th>
<th>Acciones</th>
</thead>
<tbody>
{% for sale in sales %}
<tr>
<td>{{ sale.show_date }}</td>
<td>{{ sale.invoice_number }}</td>
<td>{{ sale.client.full_name }}</td>
<td>${{ sale.amount_with_discount}}</td>
<td>
<div class="button-group">
<a href="#" class="button warning tiny" data-toggle="modalView{{sale.pk}}"><i class="fi-eye"></i></a>
</td>
</div>
</tr>
<div class="tiny reveal" id="modalView{{sale.pk}}" style="background-color:rgb(51,51,51);" data-reveal data-close-on-click="true" data-animation-in="spin-in" data-animation-out="spin-out">
<h4 class="cell" style="text-align: center;">Detalle de Venta</h4>
</div>
{% endfor %}
</tbody>
</table>
{% if is_paginated %}
<ul class="pagination cell medium-12">
{% if page_obj.has_previous %}
<li><a href="?page={{ page_obj.previous_page_number }}" style="color: wheat;">«</a></li>
{% else %}
<li class="disabled"><span style="color: wheat;">«</span></li>
{% endif %} {% for i in paginator.page_range %} {% if page_obj.number == i %}
<li class="active">
<span style="color: wheat;">{{ i }} <span class="sr-only">(actual)</span></span>
</li>
{% else %}
<li><a href="?page={{ i }}" style="color: wheat;">{{ i }}</a></li>
{% endif %} {% endfor %} {% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}" style="color: wheat;">»</a></li>
{% else %}
<li class="disabled"><span style="color: wheat;">»</span></li>
{% endif %}
</ul>
{% endif %}
</div>
{% endblock panel-content %}
The reason this fails is because if you click on the next page, the rest of the querystring (the search parameters) are not passed to the following request.
You can encode the rest of the querystring with:
class ListSales(LoginRequiredMixin, ListView):
# …
def urencode_filter(self):
qd = self.request.GET.copy()
qd.pop(self.page_kwarg, None)
return qd.urencode()
In the links to the other pages, you then add the urlencode_filter()
value with:
<li><a href="?page={{ page_obj.previous_page_number }}&{{ view.urlencode_filter }}" style="color: wheat;">«</a></li>
and do this with all links to previous, next, and arbitrary pages.