I got a problem with pagination after using django_filter in my TemplateView. Before use django_filter, my pagination was working normally but now it show all the items in every page, I've been looking on the internet but I didn't find a good solution for this. how can I fix it? thanks
my filter.py
class SnippetFilter(django_filters.FilterSet):
area = []
tecnology = Technology.objects.values('parent_area').distinct().order_by('parent_area_id')
for a in tecnology:
area.append(a['parent_area'])
parent_area = django_filters.ModelMultipleChoiceFilter(queryset=ApplicationArea.objects.filter(id__in=area), widget=forms.CheckboxSelectMultiple)
class Meta:
model = Technology
fields = ['title', 'category', 'kind', 'patent', 'patent_type', 'parent_area']
my view.py
class TechnologyListView(LoginRequiredMixin, ListView):
model = Technology
template_name = "technology/technology.html"
paginate_by = 9
def get_queryset(self, *args, **kwargs):
queryset = super(TechnologyListView, self).get_queryset()
if self.request.user.is_authenticated and self.request.user.is_superuser or self.request.user.is_authenticated and self.request.user.is_staff:
queryset = Technology.objects.all()
elif self.request.user.is_authenticated and self.request.user.is_technology:
queryset = Technology.objects.filter(user=self.request.user).order_by('-id')
return queryset
def get_context_data(self, **kwargs):
selected_elements = []
data = super(TechnologyListView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated and self.request.user.is_technology:
data['finished'] = Technology.objects.filter(user=self.request.user, category=0).count()
data['developed'] = Technology.objects.filter(user=self.request.user, category=1).count()
data['product'] = Technology.objects.filter(user=self.request.user, kind=0).count()
data['process'] = Technology.objects.filter(user=self.request.user, kind=1).count()
data['software'] = Technology.objects.filter(user=self.request.user, kind=2).count()
data['deposited'] = Technology.objects.filter(user=self.request.user, patent=0).count()
data['licensed'] = Technology.objects.filter(user=self.request.user, patent=1).count()
data['donthave'] = Technology.objects.filter(user=self.request.user, patent=2).count()
elif self.request.user.is_authenticated and self.request.user.is_superuser or self.request.user.is_authenticated and self.request.user.is_staff :
data['finished'] = Technology.objects.filter(category=0).count()
data['developed'] = Technology.objects.filter(category=1).count()
data['product'] = Technology.objects.filter(kind=0).count()
data['process'] = Technology.objects.filter(kind=1).count()
data['software'] = Technology.objects.filter(kind=2).count()
data['deposited'] = Technology.objects.filter(patent=0).count()
data['licensed'] = Technology.objects.filter(patent=1).count()
data['dontthave'] = Technology.objects.filter(patent=2).count()
data['filter'] = SnippetFilter(self.request.GET, queryset=self.get_queryset())
return data
template.html
<div class="container-fluid" >
<div class="row">
<div class="col-sm-2">
<div style="margin-top:20%; margin-bottom:25% ">
<h1 class="title text-center">Filtro:</h1>
<form method="GET" action="{% url 'technology:tech_index' %}" novalidate>
{{filter.form|bootstrap}}
<a class="btn btn-rw btn-danger" href="{% url 'technology:tech_index' %}">Limpar Filtro</a>
<input type='submit' value='Procurar' class='btn btn-rw btn-primary'>
</form>
</div>
</div>
<div class="col-sm-8 col-sm-offset-1">
<br>
<a class="btn btn-rw btn-primary" href="{% url 'technology:create_tech' %}"><i class="fa fa-bolt">
</i>Adicionar Tecnologia</a>
<h1 class="title text-center">Minhas Tecnologias</h1>
{% if filter.qs.count > 0 %}
<div class="tab-content tab-shop mt15" style="align-items: center !important;">
<div class="row" >
<div class="col-sm-4 col-md-4 col-lg-4">
<canvas id="category"></canvas>
</div>
<div class="col-sm-4 col-md-4 col-lg-4">
<canvas id="type" ></canvas>
</div>
<div class="col-sm-4 col-md-4 col-lg-4">
<canvas id="patent"></canvas>
</div>
<!-- <div class="col-lg-3 col-md-3 col-sm-3">
<canvas id="area_ap" width="80" height="80"></canvas>
</div> -->
</div>
<br>
</div>
<br>
<div class="tab-content tab-shop mt15">
<div id="home" class="tab-pane row fade in active">
{% for item in filter.qs %}
<div class="col-lg-4 col-md-4 col-sm-6 mb30">
<div class="view no-margin" style="background-color: #cfcfcf">
<!-- Blog Thumb -->
<div class="product-container">
{% if item.area_img %}
<img class="img-responsive full-width" style="width:100%; height:200px" src="{{item.area_img.image.url}}" alt="...">
{% else %}
<img class="img-responsive full-width" style="width:100%; height:200px" src="{% static 'images/notavailable.png' %}" alt="...">
{% endif %}
</div>
<div class="mask">
<div class="image-hover-content">
<!-- Zoom + Blog Link -->
<a href="{% url 'technology:detail_tech' item.pk %}" >
<div class="image-icon-holder"><span data-toggle="tooltip" data-placement="top" title="Visualizar" class="ion-eye image-icons"style="color:#fff"></span></div>
</a>
{% if request.user.is_authenticated and request.user.is_technology %}
<a href="{% url 'technology:update_tech' item.pk %}">
<div class="image-icon-holder"><span data-toggle="tooltip" data-placement="top" title="Editar" class="ion-edit image-icons" style="color:#fff"></span></div>
</a>
<a data-toggle="modal" data-target="#delete-{{item.pk}}">
<div class="image-icon-holder"><span data-toggle="tooltip" data-placement="top" title="Deletar" class="ion-ios7-trash image-icons" style="color:red"></span></div>
</a>
{% endif %}
<div class="modal fade" id="delete-{{item.pk}}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content text-center">
<form action="{% url 'technology:delete_tech' pk=item.pk %}" method="post">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h2>Deletar</h2>
</div>
<div class="modal-body">
<p>Você deseja realmente deletar "{{ item }}"?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" data-dismiss="modal">Voltar</button>
<input class="btn btn-danger" type="submit" value="Confirmar" />
</div>
</form>
</div>
</div>
</div>
</div><!-- /image hover content -->
</div><!-- /mask-->
</div>
<div class="shop-product content-box-shadow">
<a href="{% url 'technology:update_tech' item.pk %}"><h2>{{item.title}}</h2></a>
{% if item.description %}
<p>{{item.description|truncatechars:40}}</p>
{% else %}
<p class="text-danger">Não há descrição</p>
{% endif %}
</div>
</div>
{% if forloop.counter|divisibleby:4 %}
</li>
<li>
{% endif %}
{% endfor %}
</div>
</div>
{% include "includes/paginator.html" %}
{% else %}
<div class="tab-content tab-shop mt15 text-center " style="padding-top: 25%; padding-bottom: 25%">
<div class="row">
<h1 class="text-info">Nenhuma tecnologia cadastrada</h1>
</div>
</div>
{% endif %}
</div>
</div>
paginator.html
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a href="?page={{ page_obj.previous_page_number }}">«</a>
</li>
{% else %}
<li class="disabled"><span class="page-link">«
</span></li>
{% endif %}
{% for page_num in paginator.page_range %}
{% if page_obj.number == page_num %}
<li class="page-item active">
<span class="page-link">
{{ page_num }}
<span class="sr-only">(current)</span>
</span>
</li>
{% elif page_num > page_obj.number|add:'-2' and page_num < page_obj.number|add:4 %}
<li class="page-item">
<a class="page-link" href="?page={{ page_num }}">{{page_num}}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">»</a></li>
{% else %}
<li class="page-item disabled">
<span class="page-link">
»
</span>
</li>
{% endif %}
</ul>
{% endif %}
I had this issue for awhile, and found this solution to be my favourite.
django-filter's FilterView already supports pagination the same as ListView, except it's not super obvious how to make it work. You can try this by changing 'page=2' in the address bar of your browser while the filters are applied and sure enough it will go to the next correct page.
So to make it work is only a few steps...
Create a view mixin, which separates out 'page' keyword (default for django's pagination) and returns the remaining query string as a new template context variable.
class PaginatedFilterViews(View):
def get_context_data(self, **kwargs):
context = super(PaginatedFilterViews, self).get_context_data(**kwargs)
if self.request.GET:
querystring = self.request.GET.copy()
if self.request.GET.get('page'):
del querystring['page']
context['querystring'] = querystring.urlencode()
return context
Then include this new object in all the FilterViews you want paginated... ie:
class FilteredList(PaginatedFilterViews, FilterView):
model = Whatever
paginate_by = 10 # or whatever
# the rest of your view code
And update your pagination template to insert the rest of django-filter's query string...
{% if page_obj.has_previous %}
<li>
<a href="?page=1{% if querystring %}&{{ querystring }}{% endif %}">
<i class="icon-page-first"></i>
<span class="btn-text">First</span>
</a>
</li>
<li>
<a href="?page={{ page_obj.previous_page_number }}{% if querystring %}&{{ querystring }}{% querystring %}">
<i class="icon-page-back"></i>
<span class="btn-text">Prev</span>
</a>
</li>
{% else %}
<li class="disabled">
<span class="icon-page-first">
<span class="btn-text">First</span>
</span>
</li>
<li class="disabled">
<span class="icon-page-back">
<span class="btn-text">Prev</span>
</span>
</li>
{# etc etc #}
{% endif %}
Works well for me across many views, and no other 3rd party dependencies are required.
Personally I use django-tables with django-filter and that takes care of the pagination for me, so I'm no expert on this. However it seems that you need to paginate the results of the filter once you have them in your view. Perhaps something like this?
paginator = Paginator(data, 10)
Check out this posting on SO. Django Filter with Pagination and also this website explains how to do it generically. https://djangopy.org/how-to/pagination-with-django/
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