django-filter use paginations
This worked for me:
in my template instead of using this
<li><a href="?page={{ i }}">{{ i }}</a></li>
I wrote this:
{% if 'whatever_parameter_you_use_to_filter' in request.get_full_path %} <li><a href="{{ request.get_full_path }}&page={{ i }}"{{ i }}</a></li>{% else %} <li><a href="?page={{ i }}">{{ i }}</a></li>{% endif %}
I hope it helps :)
To use Django Filter and paginate the filtered result you can do the following:
Create a filter class for your model:
On
my_project/my_app/filters.py
:import django_filtersclass MyModelFilter(django_filters.FilterSet): class Meta: model = MyModel # Declare all your model fields by which you will filter # your queryset here: fields = ['field_1', 'field_2', ...]
Every
FilterSet
object has a.qs
property which contains the filtered queryset and you can even override it if you want.We will paginate the
.qs
property of ourMyModelFilter
:On
my_project/my_app/views.py
:from . import filtersfrom django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerdef my_view(request): # BTW you do not need .all() after a .filter() # local_url.objects.filter(global_url__id=1) will do filtered_qs = filters.MyModelFilter( request.GET, queryset=MyModel.objects.all() ).qs paginator = Paginator(filtered_qs, YOUR_PAGE_SIZE) page = request.GET.get('page') try: response = paginator.page(page) except PageNotAnInteger: response = paginator.page(1) except EmptyPage: response = paginator.page(paginator.num_pages) return render( request, 'your_template.html', {'response': response} )
And there you have it!
PS_1: Django filter in my experience, "plays" better with Django Rest Framework.
PS_2: If you are about to utilize DRF, I have written an example on how to use pagination in a function based view which you can easily combine with a FilterSet
:
@api_view(['GET',])def my_function_based_list_view(request): paginator = PageNumberPagination() filtered_set = filters.MyModelFilter( request.GET, queryset=MyModel.objects.all() ).qs context = paginator.paginate_queryset(filtered_set, request) serializer = MyModelSerializer(context, many=True) return paginator.get_paginated_response(serializer.data)
To add to the answers, I did it with html tables too along with django-filters and Paginator. Below are my view and template files. The template tag is needed to make sure you pass the right parameters to the pagination url.
search_view.py
from django.shortcuts import renderfrom app.models.filters_model import ApiStatusFilterfrom app.models.api_status import ApiStatusfrom django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerfrom datetime import datetime, timedeltadef status(request): all_entries_ordered = ApiStatus.objects.values().order_by('-created_at')[:200] for dictionarys in all_entries_ordered: dictionarys apistatus_list = ApiStatus.objects.values().order_by('-created_at') apistatus_filter = ApiStatusFilter(request.GET, queryset=apistatus_list) paginator = Paginator(apistatus_filter.qs, 10) page = request.GET.get('page') try: dataqs = paginator.page(page) except PageNotAnInteger: dataqs = paginator.page(1) except EmptyPage: dataqs = paginator.page(paginator.num_pages) return render(request, 'status_page_template.html', {'dictionarys': dictionarys, 'apistatus_filter': apistatus_filter, 'dataqs': dataqs, 'allobjects': apistatus_list})
status_template.html
{% load static %}{% load my_templatetags %}<!DOCTYPE html><html lang="en"> <head> <link rel="stylesheet" type="text/css" href="{% static 'css/table_styling.css' %}"> <meta charset="UTF-8"> <title>TEST</title> </head> <body> <table> <thead> <tr> {% for keys in dictionarys.keys %} <th>{{ keys }}</th> {% endfor %} </tr> </thead> <form method="get"> {{ apistatus_filter.form.as_p }} <button type="submit">Search</button> {% for user in dataqs.object_list %} <tr> <td>{{ user.id }}</td> <td>{{ user.date_time }}</td> <td>{{ user.log }}</td> </tr> {% endfor %} </form> </tbody> </table> <div class="pagination"> <span> {% if dataqs.has_previous %} <a href="?{% query_transform request page=1 %}">« first</a> <a href="?{% query_transform request page=dataqs.previous_page_number %}">previous</a> {% endif %} <span class="current"> Page {{ dataqs.number }} of {{ dataqs.paginator.num_pages }}. </span> {% if dataqs.has_next %} <a href="?{% query_transform request page=dataqs.next_page_number %}">next</a> <a href="?{% query_transform request page=dataqs.paginator.num_pages %}">last »</a> {% endif %} </span> </div> </body></html>
my_templatetags.py
from django import templateregister = template.Library()@register.simple_tagdef query_transform(request, **kwargs): updated = request.GET.copy() for k, v in kwargs.items(): if v is not None: updated[k] = v else: updated.pop(k, 0) return updated.urlencode()