Django Context Processors
Adding global variables to all templates
đ¯ What are Context Processors?
Context processors add variables to the template context automatically for every template. They make data available globally without passing it from every view, perfect for site-wide information like user data or settings.
# Simple context processor
def site_info(request):
return {
'site_name': 'My Website',
'year': 2024
}
Built-in Context Processors
auth
Provides user and permissions
'django.contrib.auth.context_processors.auth'
# Available in templates:
# {{ user }}
# {{ perms }}
request
Adds request object to context
'django.template.context_processors.request'
# Available in templates:
# {{ request.path }}
# {{ request.user }}
messages
Provides message framework
'django.contrib.messages.context_processors.messages'
# Available in templates:
# {{ messages }}
media
Adds MEDIA_URL to context
'django.template.context_processors.media'
# Available in templates:
# {{ MEDIA_URL }}
đš Creating Custom Context Processor
Context processors are simple functions that return dictionaries. The keys become variable names available in all templates, making it easy to share common data across your entire site.
# context_processors.py
from django.conf import settings
def site_settings(request):
"""Add site-wide settings to all templates"""
return {
'SITE_NAME': 'My Awesome Site',
'SITE_TAGLINE': 'Building amazing things',
'CONTACT_EMAIL': '[email protected]',
'CURRENT_YEAR': 2024,
}
def user_info(request):
"""Add user-specific information"""
if request.user.is_authenticated:
return {
'unread_messages': request.user.messages.filter(read=False).count(),
'user_avatar': request.user.profile.avatar.url,
}
return {}
Now Available in All Templates:
{{ SITE_NAME }} â "My Awesome Site"
{{ CURRENT_YEAR }} â 2024
{{ unread_messages }} â 5
đš Registering Context Processors
Add your context processor to the TEMPLATES setting in settings.py. Django will automatically call these functions for every template render.
# settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'myapp.context_processors.site_settings', # Your custom processor
'myapp.context_processors.user_info', # Another custom processor
],
},
},
]
đš Using Context Variables in Templates
Once registered, context processor variables are automatically available in all templates without passing them from views.
<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ SITE_NAME }} - {{ SITE_TAGLINE }}</title>
</head>
<body>
<header>
<h1>{{ SITE_NAME }}</h1>
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}!</p>
<p>You have {{ unread_messages }} unread messages</p>
{% endif %}
</header>
<footer>
<p>Š {{ CURRENT_YEAR }} {{ SITE_NAME }}</p>
<p>Contact: {{ CONTACT_EMAIL }}</p>
</footer>
</body>
</html>
Rendered Output:
My Awesome Site - Building amazing things
Welcome, john_doe!
You have 5 unread messages
Š 2025 My Awesome Site
Contact: [email protected]
đš Practical Example: Navigation Menu
Create a context processor that provides navigation menu items to all templates, making it easy to maintain consistent navigation across your site.
# context_processors.py
def navigation(request):
"""Provide navigation menu items"""
menu_items = [
{'name': 'Home', 'url': '/', 'icon': 'đ '},
{'name': 'About', 'url': '/about/', 'icon': 'âšī¸'},
{'name': 'Blog', 'url': '/blog/', 'icon': 'đ'},
{'name': 'Contact', 'url': '/contact/', 'icon': 'đ§'},
]
# Add admin link for staff users
if request.user.is_staff:
menu_items.append({
'name': 'Admin',
'url': '/admin/',
'icon': 'âī¸'
})
return {
'nav_menu': menu_items,
'current_path': request.path,
}
<!-- Template usage -->
<nav>
<ul>
{% for item in nav_menu %}
<li class="{% if current_path == item.url %}active{% endif %}">
<a href="{{ item.url }}">
{{ item.icon }} {{ item.name }}
</a>
</li>
{% endfor %}
</ul>
</nav>
Rendered Navigation:
đ Home | âšī¸ About | đ Blog | đ§ Contact | âī¸ Admin
đš Performance Considerations
Context processors run on every template render, so keep them efficient:
- Avoid database queries: Cache results or use select_related
- Keep it lightweight: Only add essential data
- Use caching: Cache expensive computations
- Conditional logic: Only compute what's needed
# Good: Efficient context processor
from django.core.cache import cache
def cached_stats(request):
stats = cache.get('site_stats')
if not stats:
stats = {
'total_users': User.objects.count(),
'total_posts': Post.objects.count(),
}
cache.set('site_stats', stats, 300) # Cache for 5 minutes
return stats