Django Filter Package – Part-1
The Django Filter is a Django Package that lets you create filters effortlessly. To use this package we must install pip install django-filter
by typing into the terminal. Django Filter provides an advantage over other queryset filtering methods as it can be reused and is simple to set up less complex than other queryset filtering methods.
After we complete all 3 parts below is how our template will be rendered.

Django Filter Package Final Ourpur
Table of Contents
- Setup Project
- Creating Models and Migration
- Getting Started with a simple example
- Generating filter lookups with a dictionary
- Using relationship with filter
- Conclusion
Setup Project
If you want to know how to set up Django Project with apps than click on this link.
After you have successfully set up project goto root directory of the project and install pip install django-filter
through terminal.
After installation of django-filter
you must register it in settings.py file in INSTALLED_APPS
.
INSTALLED_APPS = [ ... 'django_filters', ]
Now create an app and name it as filter_and_pagination.
And register this to INSTALLED_APPS
.
INSTALLED_APPS = [ ... 'django_filters', 'filter_and_pagination.apps.FilterAndPaginationConfig', ]
Create urls.py file in app(filter_and_pagination) and add below code.
from django.urls import path, re_path from filter_and_pagination import views app_name = 'filter_and_pagination' urlpatterns = [ ]
You can see that urlpatterns
has no routes we’ll create that later.
The include
app(filter_and_pagination) urls.py file in projects root’s url.py file.
urlpatterns = [ ... path('filter_and_pagination/', include('filter_and_pagination.urls'), name='filter_and_pagination'), ]
Creating Models and Migration
Next, we’ll create Models and Migrate them to our database. Here we’ll take the example of Books and Authors.
An Author can have multiple books and Books have a Foreign key relationship with Authors.
Creating Models
Navigate to the app in models.py file.
from django.db import models class Book(models.Model): BOOK_STATUS=( ('PUBLISHED', 'Published'), ('ON_HOLD', 'On Hold'), ) id = models.AutoField(primary_key=True) book_name = models.CharField(max_length=255) author = models.ForeignKey('Author',on_delete=models.CASCADE,related_name='author') status = models.CharField(max_length=255, choices = BOOK_STATUS) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table="books" verbose_name="Book" verbose_name_plural="Books" def __str__(self): return self.book_name @property def get_status_verbose_name(self): for row in range(0,2): if self.BOOK_STATUS[row][0] == self.status: status_verbose = self.BOOK_STATUS[row][1] break return status_verbose class Author(models.Model): id = models.AutoField(primary_key=True) author_name = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "authors" verbose_name = "Author" verbose_name_plural = "Authors" def __str__(self): return self.author_name @property def get_books_count(self): return Book.objects.filter(author=self.id).count()
We have two models Book
and Author
. Model Book
has ForeignKey relations with Author
model.
The Book
models have a property called get_status_verbose_name
this will return the verbose name of the book’s status.
Suppose if Book status is PUBLISHED
then it will display Published
for human readability.
The Author
Models do not have anything special but it has get_books_count
property which returns the count of Books written by the Author.
Again this does not check how many published or on hold. If you want then you can create another property or modify the existing one.
Migration
open terminal/Command Prompt from the root directory and follow the below steps.
python manage.py makemigrations
this will create a migration file for all apps.python manage.py migrate
this will migrate to the database and create tables.
Getting Started with a simple example
In app(filter_and_pagination) create filter.py file. Django-Filters uses django_filters.FilterSet
to generate filter results.
The result is returned as queryset and only we have to do is specify model
, fields
. The django_filters.FilterSet
will generate form, query filtering by itself.
Let us look at a simple example in the filter.py file.
import django_filters from filter_and_pagination.models import Book,Author class BookFilterExp1(django_filters.FilterSet): book_name = django_filters.CharFilter(lookup_expr='iexact') class Meta: model = Book fields = ['status']
In BookFilterExp1
the filter we have two fields book_name
, status
.We have specified lookup_expr to book_name. The lookup_expr is used for mapping filters to models columns and field in status
. we have not specified lookup_expr in this case it will consider exact
as its default expression type.
Accessing in views
We’ll create a route for view.
Navigate to apps(filter_and_pagination) urls.py file.
app_name = 'filter_and_pagination' urlpatterns = [ path('filter_example_1', views.filter_example_1, name='filter_example_1'), ]
Create view filter_example_1 in apps(filter_and_pagination) views.py file.
def filter_example_1(request): books = BookFilterExp1(request.GET) ctx={ "books" : books } path='filter_and_pagination/filter_listing.html' return render(request,path,ctx)
To display data create template in path=’apps(filter_and_pagination)/templates/filter_and_pagination/filter_listing.html’.
The template file must be at above mentioned else you make get an error. If you have knowledge of templates than you can place in any were.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Book</title> </head> <body> <div> <div style="border: 1px dashed #333;" > <h5 style="text-align: center;" >Book Filtering</h5> </div> <div style="" > <div> <h5>Filter Form</h5> <div> <form action="" method="get"> {{books.form}} <input type="submit" value="Filter"> </form> </div> </div> <table border="1" style="border-collapse: collapse"> <thead> <tr> <th>Sl no</th> <th>Book Name</th> <th>Author</th> <th>Book Status</th> <th>Total Books Count</th> </tr> </thead> <tbody> {% for book in books.qs %} <tr> <td>{{forloop.counter}}</td> <td>{{book.book_name}}</td> <td>({{book.author.id}}) <strong>{{book.author.author_name}}</strong></td> <td>{{book.get_status_verbose_name}}</td> <td>{{book.author.get_books_count}}</td> </tr> {% endfor %} </tbody> </table> </div> </div> </body> </html>
We have to use books.qs
for displaying books has it consists of filtered querysets.
Output

Listing authors
Generating filter lookups with a dictionary
We Specified book_name
as CharFilter
with means it uses CharField
. It is not necessary to specify field type we can just pass values inside the dictionary and let Django-Filter
decide which field to use for displaying in form.
Suppose we have not specified field for status
but it automatically considered to display in select
the tag.
class BookFilterExp1_2(django_filters.FilterSet): class Meta: model = Book fields = { 'book_name' : ['icontains', 'iexact'], 'author__author_name' : ['icontains'], 'status' : ['exact'], }
The author__author_name
is a ForeignKey relation for the Book and Author model. So the Author Name field will also be displayed.
We import BookFilterExp1_2
Filter to views and make new view function.
from filter_and_pagination.filter import (BookFilterExp1,BookFilterExp1_2) def filter_example_1_2(request): # this is a filter example path='filter_and_pagination/filter_listing.html' books = BookFilterExp1_2(request.GET) ctx={ "books" : books } return render(request,path,ctx)
Add to route urls.py file
app_name = 'filter_and_pagination' urlpatterns = [ ... path('filter_example_1_2', views.filter_example_1_2, name='filter_example_1_2'), ]
Output

Adding HTML elements for List Filter
Using relationship with filter
This example is similar to that of the above once. But we have specified a filter type for author_name
. This filter is of CharFilter and it uses CharField for form rendering.It also has Label
which means HTML `<label></label>` Tag.
The field_name
is for model field name or as relationship example : author__author_name
is converted to author__author_name__icontains
by Django-Filter
while querying.
class BookFilterExp2(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') class Meta: model = Book fields = ['status']
Lets make a view for this filter
from filter_and_pagination.filter import (BookFilterExp1,BookFilterExp1_2,BookFilterExp2) def filter_example_2(request): # this is a filter example path='filter_and_pagination/filter_listing.html' books = BookFilterExp2(request.GET) ctx={ "books" : books } return render(request,path,ctx)
Make routes for view filter_example_2 function
app_name = 'filter_and_pagination' urlpatterns = [ path('listing', views.list_data, name='listing'), path('filter_example_1', views.filter_example_1, name='filter_example_1'), path('filter_example_1_2', views.filter_example_1_2, name='filter_example_1_2'), path('filter_example_2', views.filter_example_2, name='filter_example_2'), ]
Result

List Filtering
Conclusion
This is the end of Part 1 of Django Filter Package – Part-1 in the next part we’ll learn about custom methods and modifying queries.
Related Posts
- How to Install Django | Start Project, Create App and Run Project
- Django – How to Display Images in Template from Static Directory




