django-filter use paginations django-filter use paginations django django

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:

  1. 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', ...]
  2. Every FilterSet object has a .qs property which contains the filtered queryset and you can even override it if you want.

  3. We will paginate the .qs property of our MyModelFilter:

    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()