Hello! Welcome back to your Django journey.
In the last lesson, we focused on bridging the gap between your Python logic and your HTML templates by passing context data from views. You learned how to package data into a dictionary and access it in the template using {{ variable }} syntax.
This lesson takes the next logical step. Now that you can get data into your templates, you'll learn how to control and format it once it's there. We'll explore two powerful features of the Django Template Language (DTL): template tags and template filters. This will allow you to implement logic, create robust URLs, and format your data for a clean presentation.
This lesson directly addresses the learning outcome: Apply template tags (e.g., {% url %}) and filters to control logic and formatting.

1. The Building Blocks: Tags vs. Filters
Before we dive in, let's clarify the difference between tags and filters.
- Tags (
{% tag %}): These provide the logic and control flow inside your template. Think of them as the template language's keywords and functions. You've already used{% extends %}and{% for %}. Today, we'll cover tags for conditional logic and, most importantly, for creating URLs. - Filters (
{{ variable|filter }}): These are used to modify how a variable is displayed. They are simple transformations you can apply to your data right before it's rendered. For example, making text uppercase or formatting a date.
2. Template Tags: Adding Logic to Your Templates
Template tags are your tools for making templates smart. They handle everything from loops and conditional statements to creating dynamic URLs.
Looping and Conditional Rendering
You've already seen the {% for %} loop. A common requirement when looping is to show a different message if the list you're iterating over is empty. While you could wrap your loop in an {% if %} block, Django provides a more elegant tag for this: {% empty %}.
Let's also look at the {% url %} tag, which is one of the most important tags for building maintainable applications. Hard-coding URLs in your templates (e.g., <a href="/tasks/3/">) is a bad practice. If you ever change that URL structure in urls.py, you have to find and replace it in every single template. The {% url %} tag solves this by dynamically generating the URL based on the name you gave your URL pattern.
The following video provides an excellent, practical demonstration of these concepts.
Django - Detail Pages & the {% url %} template tag!
The video "Django - Detail Pages & the {% url %} template tag!" from BugBytes clearly explains why hard-coding URLs is fragile and how the {% url %} tag provides a robust solution. It also gives a great example of using {% for...empty %}.
Watch from 05:14 to 13:37. Pay close attention to: How the {% url %} tag uses the name defined in your urls.py file. The concept of namespacing URLs (e.g., {% url 'polls:detail' ... %}) to avoid conflicts between different apps. How to use {% empty %} inside a for loop to handle cases with no data.
Key takeaways from the video:
- Avoid Hard-coding URLs: Always use
{% url 'name_of_url' %}. This makes your project much easier to maintain. - Use Namespacing: As your projects grow, you'll have multiple apps. To prevent URL name collisions (e.g., two apps having an
indexURL), define anapp_namein your app'surls.pyand reference it like{% url 'my_app:index' %}. - Handle Empty States: The
{% for ... empty %}block is the cleanest way to display a fallback message when a list is empty.
Test your understanding!
Imagine your project has a users app and a tasks app. Both have a URL pattern named list. How would you create a link specifically to the task list page in a template?
Show answer
Assuming you have app_name = 'tasks' in your tasks/urls.py, you would use the namespaced URL tag:<a href="{% url 'tasks:list' %}">View Tasks</a>
3. Template Filters: Formatting Your Data
Now that we've covered logic with tags, let's look at presentation with filters. Filters are applied with the pipe character (|) and can even be chained together.
For a comprehensive look at the most common filters, the following article is an excellent reference.
Django Templates: Built-In Tags and Filters
The article "Django Templates: Built-In Tags and Filters" from Real Python offers a clear, well-structured guide to the most useful built-in filters.
Read the section titled "Exploring Key Template Filters". Focus on understanding the syntax and the purpose of filters in these categories: String Filters: upper, lower, cut. List Filters: length, join, pluralize. Date and Time Filters: date, time, timesince.
To see some of these filters in action, the following video gives quick, practical demonstrations.
Try DJANGO Tutorial - 20 - Template Tags and Filters
The video "Template Tags and Filters" by CodingEntrepreneurs provides quick visual examples of applying filters.
Watch from 01:42 to 04:24. This will show you how to apply and chain filters like capfirst and upper, and it introduces the important safe filter for rendering HTML.
A particularly important filter to be aware of is safe. By default, Django escapes all HTML in variables to prevent cross-site scripting (XSS) attacks. This means if a variable contains <b>Hello</b>, it will render as the literal text <b>Hello</b>, not as Hello. The safe filter tells Django "I trust this content, render it as actual HTML." Use it with caution and only on content you generate or have sanitized yourself.
4. Practice: Upgrading Your Task List
Let's apply these new tools to your task list application. We'll add due dates and use tags and filters to display them nicely.
-
Update your View (
tasks/views.py)
Let's add adatetimeobject to our dummy data. We'll need to importdatetimefrom Python's standard library.# tasks/views.py from django.shortcuts import render from datetime import datetime # Import the datetime module def tasks_view(request): # Add a due_date to each task dummy_tasks = [ {'id': 1, 'title': 'Learn Django Views', 'completed': True, 'due_date': datetime(2024, 8, 1)}, {'id': 2, 'title': 'Build a Template', 'completed': True, 'due_date': datetime(2024, 8, 5)}, {'id': 3, 'title': 'Understand Context', 'completed': False, 'due_date': datetime(2024, 8, 10)}, {'id': 4, 'title': 'create a model', 'completed': False, 'due_date': datetime(2024, 8, 15)}, ] # We'll also pass an empty list to test the {% empty %} tag notes = [] context = { 'page_title': 'My To-Do List', 'tasks': dummy_tasks, 'task_count': len(dummy_tasks), 'notes': notes } return render(request, 'tasks/task_list.html', context) -
Update your Template (
tasks/templates/tasks/task_list.html)
Now, let's use filters to format the title and date, and use theemptytag for our newnoteslist.{% extends "base.html" %} {% block title %}{{ page_title }}{% endblock %} {% block content %} <h1>{{ page_title }}</h1> <p>You have {{ task_count }} task{{ task_count|pluralize }}.</p> <ul> {% for task in tasks %} <li> <!-- Use the capfirst filter to capitalize the title --> {{ task.title|capfirst }} - Status: {% if task.completed %}Done{% else %}Pending{% endif %} | <!-- Use the date filter to format the due date --> Due: {{ task.due_date|date:"F j, Y" }} </li> {% endfor %} </ul> <hr> <h3>Notes</h3> <ul> {% for note in notes %} <li>{{ note }}</li> {% empty %} <!-- This will be displayed because the 'notes' list is empty --> <li>You have no notes yet.</li> {% endfor %} </ul> {% endblock %}|capfirst: Capitalizes the first letter of the task title.|date:"F j, Y": Formats thedatetimeobject into a more readable format (e.g., "August 10, 2024"). You can find all the format codes in the Django documentation.|pluralize: Adds an "s" to the word "task" iftask_countis not 1.{% empty %}: Shows a message because thenoteslist we passed in the context is empty.
Save both files and refresh your browser. You should see your formatted titles, readable dates, and the "no notes" message.
Conclusion
Fantastic work! You have now unlocked the full expressive power of the Django Template Language. By combining context data with tags and filters, you can create dynamic, intelligent, and well-formatted web pages.
Key Takeaways:
- Template Tags (
{% %}): Used for logic and control flow. The{% url %}tag is essential for creating maintainable links. - Template Filters (
|): Used to format and modify data for display. Common uses include changing text case (upper,capfirst), formatting dates (date), and handling plurals (pluralize). - Separation of Concerns: Tags and filters allow you to keep presentation logic inside the template, separate from the business logic in your view.
Preview of the Next Lesson:
Our application's structure and logic are taking shape, but it still looks like a plain HTML document. In the next lesson, we will finally add some style! You will learn how to configure and serve static files like CSS and JavaScript in a Django project, allowing you to create visually appealing and interactive user interfaces.