Answer a question

I'm using the django-filter package to provide a search functionality on my List View.

Now I want to add a pagination to that view as well.
I'm trying to combine pagination to a filtered queryset, but I have no clue on how to go on.

So far, I have tried the following on views.py:

def search(request):
    qs = local_url.objects.filter(global_url__id=1).all()
    paginator = Paginator(qs, 25)
    page = request.GET.get('page')
    try:
        pub = paginator.page(page)
    except PageNotAnInteger:
        pub = paginator.page(1)
    except EmptyPage:
       pub = paginator.page(paginator.num_pages)
    url_filter = PublicationFilter(request.GET, queryset=qs)
    return render(request, 'ingester/search_list.html', {'filter': url_filter, 'publication':pub})

Answers

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_filters
    
    class 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 filters
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    def 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)
Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐