One of the most powerful features in Django is the ability to send data from your Python views to your HTML templates. This is what makes your pages dynamic. Instead of showing fixed content, you can display names, lists, articles, products, user information, and much more.
In this tutorial, you will learn how to pass data from views to templates using the context dictionary, how to display that data in HTML, and how to work with strings, numbers, lists, dictionaries, and objects inside templates.
Without passing data, your templates would only show static HTML.
Example of static HTML:
<h1>Welcome</h1>
<p>This is my website.</p>This never changes.
But with Django, you can send dynamic data such as:
This allows your web pages to change depending on the data coming from the backend.
The flow is simple:
So the view acts like the bridge between Python logic and HTML display.
In Django, data is usually passed to a template through a context dictionary.
from django.shortcuts import render
def home(request):
context = {
'name': 'Youssef'
}
return render(request, 'blog/home.html', context)<h1>Hello {{ name }}</h1><h1>Hello Youssef</h1>Here:
context is a Python dictionary'name' is the key'Youssef' is the value{{ name }} accesses that value in the templateYou are not limited to one variable. You can pass as many values as you want.
def home(request):
context = {
'name': 'Youssef',
'age': 25,
'city': 'Tetouan'
}
return render(request, 'blog/home.html', context)<h1>Hello {{ name }}</h1>
<p>Age: {{ age }}</p>
<p>City: {{ city }}</p>This makes your page more informative and dynamic.
You can pass simple data types like strings and numbers very easily.
def profile(request):
context = {
'username': 'youssef123',
'score': 92
}
return render(request, 'blog/profile.html', context)<h2>User: {{ username }}</h2>
<p>Score: {{ score }}</p>Django templates automatically display these values.
Lists are very common when you want to display multiple items.
def posts(request):
context = {
'posts': ['Post 1', 'Post 2', 'Post 3']
}
return render(request, 'blog/posts.html', context)<h1>Posts</h1>
<ul>
{% for post in posts %}
<li>{{ post }}</li>
{% endfor %}
</ul>This is very useful for blog posts, products, comments, or any list of items.
You can also pass a dictionary and access its values in the template.
def student(request):
context = {
'student': {
'name': 'Sara',
'grade': 18,
'city': 'Tangier'
}
}
return render(request, 'blog/student.html', context)
<h1>{{ student.name }}</h1>
<p>Grade: {{ student.grade }}</p>
<p>City: {{ student.city }}</p>In templates, dictionary keys can often be accessed using dot notation.
This is one of the most useful patterns in Django.
def products(request):
context = {
'products': [
{'name': 'Laptop', 'price': 800},
{'name': 'Mouse', 'price': 20},
{'name': 'Keyboard', 'price': 45}
]
}
return render(request, 'blog/products.html', context)<h1>Products</h1>
<ul>
{% for product in products %}
<li>{{ product.name }} - ${{ product.price }}</li>
{% endfor %}
</ul>This pattern is very common in real applications.
In real Django projects, you often pass database objects instead of manual dictionaries.
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})<h1>All Posts</h1>
<ul>
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>This is how Django becomes connected to real database data.
When you pass objects to templates, you can access their attributes using dot notation.
{{ post.title }}
{{ post.content }}This works for:
Once data is passed to the template, you can use conditions.
def dashboard(request):
context = {
'is_logged_in': True,
'username': 'Youssef'
}
return render(request, 'blog/dashboard.html', context){% if is_logged_in %}
<h1>Welcome {{ username }}</h1>
{% else %}
<h1>Please log in</h1>
{% endif %}This makes the page responsive to the data it receives.
You can combine passed data with template filters.
def user_info(request):
return render(request, 'blog/user.html', {'name': 'youssef'})<p>{{ name|upper }}</p>
<p>{{ name|title }}</p>
<p>{{ name|length }}</p>This allows you to format data before displaying it.
Sometimes a list may be empty.
def notifications(request):
return render(request, 'blog/notifications.html', {'messages': []}){% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% else %}
<p>No messages available.</p>
{% endif %}This is a practical way to handle empty results.
You can pass the dictionary directly inside render():
def home(request):
return render(request, 'blog/home.html', {
'name': 'Youssef',
'city': 'Tetouan'
})Or you can define it first:
def home(request):
context = {
'name': 'Youssef',
'city': 'Tetouan'
}
return render(request, 'blog/home.html', context)context is cleanerdef home(request):
posts = [
{'title': 'Introduction to Django', 'author': 'Youssef'},
{'title': 'Understanding Templates', 'author': 'Sara'},
{'title': 'Working with Views', 'author': 'Ali'},
]
return render(request, 'blog/home.html', {'posts': posts})<h1>Latest Blog Posts</h1>
<ul>
{% for post in posts %}
<li>{{ post.title }} by {{ post.author }}</li>
{% endfor %}
</ul>This is a simple but realistic example of passing dynamic data.
return render(request, 'blog/home.html')If the template expects variables, they will not exist.
If you pass:
{'username': 'Youssef'}but in the template write:
{{ name }}nothing useful will appear.
If posts is a list, you usually need {% for %} to display each item.
This is wrong:
{{ posts[0] }}Django templates are more limited than Python. Use template-friendly structures.
Be consistent in how you structure your data.
For example:
context = {
'posts': posts,
'page_title': 'Blog Home',
}This is clearer than vague names.
Think of the view as a teacher preparing materials for a classroom.
Without the teacher bringing information, the board stays empty.
In this tutorial, you learned how to pass data from Django views to templates using the context dictionary. You saw how to send simple values like strings and numbers, more complex values like lists and dictionaries, and even model objects from the database. You also learned how templates can display this data using variables, loops, conditions, and filters.
This concept is essential because it is what transforms static pages into dynamic web applications.
{{ }}{% for %}{% if %}Passing data from views to templates is one of the most important Django skills for beginners. It allows you to create pages that adapt to real data instead of showing fixed text. Once you understand this concept, you are ready to build more useful and realistic applications.