Custom Template Tags & Filters

A custom template tag or filter is a plain Python function, registered with Django's template library, that lets your own templates transform a value or compute new output beyond the built-in tags.

Learn Custom Template Tags & Filters in our free Django course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…

Part of the free Django course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll build a templatetags package and write all three kinds of extension: a filter that reshapes a value, a simple_tag that returns a computed value, and an inclusion_tag that renders a small template from a returned context — then load and use each one in a template.

What You'll Learn in This Lesson

1 Custom Filters with @register.filter

A filter is a function that takes a value, optionally one argument, and returns a transformed value. You write it in a templatetags package, decorate it with @register.filter , and apply it in a template with the pipe syntax. First you need the package itself — a templatetags folder with an empty __init__.py inside your app.

Inside blog_extras.py you create a library and register your filters on it:

Then load the library at the top of a template and apply the filters with the pipe:

2 Returning a Value with @register.simple_tag

A simple_tag is a function that returns a value and is invoked with the percent-brace tag syntax rather than the pipe. Unlike a filter, it can take any number of positional and keyword arguments, which makes it perfect for computations that need more than one input.

Call it in a template with the tag syntax — and you can capture the result into a variable with as :

3 Rendering a Snippet with @register.inclusion_tag

An inclusion_tag renders a small template instead of returning a plain value. You decorate the function with @register.inclusion_tag("some_template.html") ; the function builds and returns a context dict , and Django renders the named template with that context, inserting the result wherever the tag appears.

The small template it renders, blog/tags.html :

And calling it from any page is a single tag — no HTML strings in your Python:

🎯 Your Turn: Pass the Value First

A filter always receives the piped value as its first argument. Fill in the blank so the filter is called with word first, then the argument.

Common Errors (And How to Fix Them)

❌ "'blog_extras' is not a registered tag library"

Django can't find the library — usually a missing templatetags/__init__.py , a wrong filename, or you forgot to restart the server.

✅ Fix: ensure templatetags/__init__.py exists, the module name matches what you {% load %} , the app is in INSTALLED_APPS , then restart the server.

You used the filter without loading its library at the top of the template.

✅ Fix: add {% load blog_extras %} to the top of the template before you use the filter.

❌ "takes 1 positional argument but 2 were given"

You passed a colon argument to a filter whose function only declares the value parameter.

✅ Fix: add a second parameter to the function, e.g. def truncate_chars(value, count): , so it can accept the argument after the colon.

📋 Quick Reference

Decorator / Syntax

What It Does

register = template.Library()

Create the library tags and filters register on

@register.filter

Register a function used as value|name

@register.simple_tag

Register a function that returns a value

@register.inclusion_tag("t.html")

Render a sub-template from a returned context dict

{% load blog_extras %}

Make a library's tags and filters available in a template

🏆 Mini Challenge: Run a Tag and Build Its Usage

Write a money simple_tag, run it for real, then build the two template lines that load the library and call the tag.

❓ Frequently Asked Questions

Lesson complete — you can extend the template language!

You built a templatetags package, wrote a @register.filter applied with the pipe, a @register.simple_tag that returns a value, and a @register.inclusion_tag that renders a sub-template from a context dict — and you know they're all just plain Python functions you load with {% load %} .

🚀 Up next: Checkpoint: Models & the ORM — review everything you've learned about models and querying before moving on.

Practice quiz

Where must custom template tags and filters live to be discoverable?

  • In settings.py
  • Inside the project's urls.py
  • In a file named tags.py at the project root
  • In a templatetags package inside an installed app

Answer: In a templatetags package inside an installed app. Django only scans a templatetags package (with __init__.py) inside an installed app.

What object do you create to register tags and filters on?

  • template.Registry()
  • django.Tags()
  • template.Library()
  • register.Module()

Answer: template.Library(). You create register = template.Library() and decorate functions with it.

Which decorator registers a function used with the pipe, as value|name?

  • @register.filter
  • @register.simple_tag
  • @register.inclusion_tag
  • @register.pipe

Answer: @register.filter. @register.filter registers a filter applied with the pipe syntax in a template.

For a filter used as {{ post.body|truncate_chars:10 }}, what are the function's arguments?

  • truncate_chars(10, post.body)
  • truncate_chars(post.body, 10)
  • truncate_chars(10) only
  • truncate_chars(post.body) only

Answer: truncate_chars(post.body, 10). The piped value is the first argument and the colon argument is the second: truncate_chars(post.body, 10).

How is a simple_tag invoked in a template?

  • With the pipe, as value|tag
  • Inside double braces, as {{ tag }}
  • With the tag syntax, as {% tag arg %}
  • It cannot be called from a template

Answer: With the tag syntax, as {% tag arg %}. A simple_tag is called with the {% tag ... %} syntax, never with the pipe.

What advantage does simple_tag have over a filter?

  • It can take any number of positional and keyword arguments
  • It runs before the template loads
  • It does not need {% load %}
  • It can only return None

Answer: It can take any number of positional and keyword arguments. Unlike a filter (value plus at most one arg), a simple_tag accepts many positional and keyword args.

What does a function decorated with @register.inclusion_tag return?

  • An HttpResponse object
  • A finished HTML string
  • Nothing — it prints directly
  • A context dict used to render a named template

Answer: A context dict used to render a named template. An inclusion_tag returns a context dict, and Django renders the named template with it.

Which tag must be loaded before using tags from blog_extras.py?

  • {% import blog_extras %}
  • {% load blog_extras %}
  • {% use blog_extras %}
  • {% require blog_extras %}

Answer: {% load blog_extras %}. {% load blog_extras %} makes that library's tags and filters available in the template.

Which error means Django could not find the library you tried to load?

  • TemplateDoesNotExist
  • NoReverseMatch
  • 'blog_extras' is not a registered tag library
  • ImproperlyConfigured: missing register

Answer: 'blog_extras' is not a registered tag library. That error usually means a missing __init__.py, wrong filename, app not installed, or no server restart.

Which statement about custom tags and filters is true?

  • They are all ordinary Python functions registered on a template.Library()
  • They must be written in a special DSL, not Python
  • Filters can return only strings, never numbers
  • An inclusion_tag returns a raw HTML string

Answer: They are all ordinary Python functions registered on a template.Library(). Filters, simple_tags, and inclusion_tags are plain Python functions registered on a Library().

Continue this course