DEV Community

Ralphkay
Ralphkay

Posted on

How to simply create custom filters in Django

Django template system, allows for the use and creation of custom filters. Using custom filters is a powerful feature that allows the developer to bend the templating system to do things other than already defined.

For instance, you could develop a custom filter to return a lookup value once applied to a field ID.

You can find more information on the Official Django Documentation website

Extending your template tags with custom filters offers flexibility in your code.

Assumptions

This tutorial assumes a basic understanding of Django and Python. The project also assumes that a basic Django app has been setup already.

Keep in mind filters are functions. So a good understanding of python functions is required.

What our app will do?

The app will store students’ names and their classroom

What our filter will do?

We will define two filters: number_of_students_filter and classroom_of_students

Step 1

To define your template filters or tags you need to create a subfolder with the name templatetags in your app folder.

Add the __init__.py into your folder to render it as a module. Latest versions of python do not require this.

For example given an app named students you could have this folder structure:

students/
    templatetags/
        __init__.py
        student_filters.py

Enter fullscreen mode Exit fullscreen mode

The file name of the file to contain out custom filters is named student_filters.py

Step 2: Lets build our filters

Open the file student_filters.py :

Our first filter will be named number_of_students_filter.

def number_of_student_filter(value):

    if value

    return number_of_students

Enter fullscreen mode Exit fullscreen mode

Walkthrough

The above function like any other filter takes in an argument value. The value is the parameter that comes before the use of the pipe | symbol when writing tags with filters

{{ var | filter }}

Therefore, the value is var in this case. In the body of the function, you define what the filter must do, you can do anything but you cannot throw exceptions as filters can output them by design.

In this function, we return the number of students in our students’ table by chaining our query with the count() method.

Step 3

The function will now have to be registered as a filter. Django offers a simple interface for this.

Near the top of your file, place the following:

from django import template

register = template.Library()
Enter fullscreen mode Exit fullscreen mode

Walkthrough

It is required that for a valid library tag, the file/module must contain a variable named register which must be an instance of the templated.Library class.

To register the filter there are two major ways; using the register function itself or as a decorator.

register as a function approach

register.filter('number_of_students, number_of_students)

This takes two arguments, the first argument is the name of the filter and the second argument is the filter function itself.

register as a decorator approach

@register.filter(name='number_of_students') 
def number_of_students_filter(value):

    number_of_students = Students.objects.all().count()

    return number_of_students
Enter fullscreen mode Exit fullscreen mode

Step 4

Now, you just need to load the module, in this case, student_filters it in your template file. This is done just like the way you load static, however in this case you load it with the name of the file/module that contains the filters. In our scenario {{ load student_filters }} .

{{load student_filters }}

<!DOCTYPE>
<html>
    <title>Custom Filters</title>
    <body>

    <h1>Students</h1>
    <h2>Number of {{ students|number_of_students }}</h2>


    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Adding arguments to the filter

{{ var | classroom_of_students: 40}}

Now, how about we allow our custom filter to accept an argument, say arg. But we’ll create a new custom filter and name it classroom_students_are_in_filter. This filter will take a number as an argument and based on that number indicate whether by number of students; they are in a larger classroom or not.

@register.filter(name='classroom_of_students') 
def classroom_students_are_in_filter(value, arg):

    number_of_students = Students.objects.all().count()

    if number_of_students > arg:
        return 'Students are in the larger classroom'
    elif number_of_students < arg:
        return 'Students are in the smaller classroom'

Enter fullscreen mode Exit fullscreen mode

Walkthrough

This filter classroom_of_students takes an arg, the argument is what appears after the colon when placed in a template. This argument can be anything, string, float, integer etc. In this case it is an integer. Then run what you would like to do in the body of the function.

Don't forget to register the filter.

Voila!

Top comments (0)