When creating a web application, data is generated or stored in a standardized format. But when it's displayed to users, we need to transform it into a different form. This is when Jinja filters come in.
Filters
Filters are modifiers to manipulate the data inside variables. They can be used to change the data appearance, filter some values, or even generate new ones. To apply a filter, simply put a vertical bar (|) between the variable name and the filter name in the template.
Here is a simple filter, reverse, which, as the name suggests, reverses the order of letters in a string.
Filters are similar to usual Python functions, the only difference is their syntax. The following is the Python equivalent of the reverse filter:
def reverse(text):
return text[::-1]
reverse("rats")
|
Function |
Filter |
|
|
|
|
|
|
|
|
|
Why use filters? Why not just define functions from scratch and call them in the backend every time we need to alter data? There are several reasons:
-
Filters make life easier. They are not buggy. These filters are tested thoroughly and are used by many people;
-
They are easy to use. Even beginners can easily manipulate them;
-
Filters offer a way to alter the way data is presented on the go without having to change the backend.
Built-in and custom filters
Jinja comes with plenty of built-in filters. Reverse is just one of them.
Another one is join. Given variable var1 = [1,2,3] this is what using the filter inside a template would look like: {{var1 | join("|")}}. The output result rendered on a page then will be 1|2|3.
For a full list of Jinja's built-in filters, as well as their detailed description, you can visit Jinja's official documentation page. Here is a short list of some important ones.
|
|
Capitalizes the first letter of the word |
|
|
Checks if the value is undefined |
|
|
Sorts a dictionary |
|
|
Used for formatting string |
|
|
Applies a filter on a sequence |
|
|
Concatenates a sequence |
|
|
Replaces a sub-string with a new value |
|
|
Removes leading and trailing white space. |
You can also construct your customs filters. Just follow these two steps as shown in the examples.
-
Create a function that takes the value and returns the new, desired output.
#app.py app = Flask(__name__) def caps(text): #filter function return text.upper() @app.route("/") def index(): return render_template("index.html")Always define your filter function before rendering the template.
-
Add the function to the Jinja environment using either of these two methods:
With a decorator: @app.template-filter('name') where 'name' will be used to refer to the filter inside the template
@app.template_filter("up") # add this to the top of the filter function
def caps(text): #filter function
return text.upper()
Or with jinja_env.filters:
def caps(text): #filter function
return text.upper()
env = app.jinja_env #define the jinja enviroment
env.filters["up"] = caps #add the filter to the enviroment
To apply our new filter, we put {{"filter" | up}} in the template index.html and the result will be 'FILTER'
Date-time formatter
Let's now build a common application of filters, a date-time formatter, on which we utilize a custom-made filter.
Let's say we have a date object that we get from some source in our web application. What we will do is format this date using filters to our desired format. For this example, we will get the data from the Python datetime package and transform it in the template using a custom-made filter:
App.py:
from flask import Flask,render_template
from datetime import datetime
date = datetime.now() #the date object we want to transform
app = Flask(__name__)
@app.template_filter("prettify_date")
def do_pretty(value, format): #filter
return value.strftime(format)
@app.route("/")
def index():
return render_template("home.html" ,date = date ) #pass the variable to the template
if __name__ == "__main__":
app.run(debug = True)
We can use the following format for the data: %B %d , %Y which displays the date as month_name day, year
<!DOCTYPE html>
<html lang="en">
<head>
<title>Today</title>
</head>
<body>
<p>Today is : {{date | prettify_date("%B %d , %Y")}} </p>
</body>
</html>
The output of this template is January 1 , 1111
If your filter takes two or more arguments, the first one will always be the value you put before the pipe | in the template.
We can also form nested filters, and they are applied from left to right!
Conclusion
We can use filters to modify data into any format we want. They are functions with different syntaxes and can be used to generate new data as well as rearrange the ones that already exist. Here are a few main tips to follow whenever using filters:
-
Make sure your code is readable. Avoid using long nested filters in your template;
-
Whenever possible, use the built-in filters instead of creating new ones. Jinja has included various filters that can be useful for almost anything you might need.
-
If you have more several custom-made filters, it's better to create a separate filters.py or utils.py file and put everything inside it.