In part 2 of our post on Django Filter, we’ll dive deep and learn how we can create a custom filter method and add attributes to form.

To be persistent in our approach we’ll be taking the same example of part 1 of Django Filters .

Filter queryset using a custom method

Suppose we want to display authors who have written more than a certain number of books and also display the count of books written by each author.

So for this, we have to specify a custom method that takes queryset and parameters and returns the filtered queryset of books whose author has written a certain given number of books.

We can do it the same way as shown previous part by books count is not a part of any model so we must pass method the argument to filter.

In below example, we have specified method method="author_books_count" to filter field author_books.

The method author_books_count takes 4 arguments selfquerysetnamevalue. All fields are mandatory.

  • self: refers to that filter class itself.
  • queryset : this argument has the queryset object which is currently being used for filtering. We just need to modify this queryset and return.
  • name : this has the name of the filter field in this case author_books.
  • value`: this has filtered value for that particular field.

In app(filter_and_pagination)/filter.py file.

import django_filters
from filter_and_pagination.models import Book,Author
from django import forms

class BookFilterExp3(django_filters.FilterSet):
    book_name = django_filters.CharFilter(lookup_expr='iexact')
    author_name = django_filters.CharFilter(label="Author Name",field_name="author__author_name", lookup_expr='icontains')
    author_books = django_filters.NumberFilter(label="Number of Books Published By Author",method="author_books_count")

    class Meta:
        model = Book
        fields = ['status']

    def author_books_count(self, queryset, name, value):
        authors_qs = Author.objects.all()
        authors_id = []
        for author in authors_qs:
            count = Book.objects.filter(author=author).count()
            if count >= value:
                authors_id.append(author.id)

        qs = Book.objects.filter(author__in=authors_id)                    
        return qs

Now, let’s make a view and add it to the urls.py file.

def filter_example_3(request):
    books = BookFilterExp3(request.GET)
    ctx={
        "books" : books
    }
    path='filter_and_pagination/filter_listing.html'
    return render(request,path,ctx)
urlpatterns = [
    ...
    path('filter_example_3', views.filter_example_3, name='filter_example_3'),
]

#django framework #python #django #learn python

Django Filter Package - Part-2 - The Code Learners
5.05 GEEK