How Context Reaches a Template
The context is the dictionary-like object that maps names to values available inside a template; a view builds it explicitly (render(request, 'page.html', {'articles': articles})) or a generic CBV builds it automatically via get_context_data(). Beyond what the view supplies, Django merges in output from context processors — functions listed in TEMPLATES['OPTIONS']['context_processors'] such as django.template.context_processors.request or django.contrib.auth.context_processors.auth — which is why {{ user }} and {{ request }} are available in every template without every single view explicitly adding them. Context processors only run for templates rendered through RequestContext (which render() and generic CBVs use by default), not for Template().render() called with a plain Context.
Cricket analogy: It's like ground-staff prep before a match: the head groundsman (view) sets the pitch specifics, but the venue's standing facilities like floodlights and the scoreboard (context processors) are already wired in for every match automatically.
Writing Custom Template Tags
When built-in tags and filters can't express a piece of presentation logic, you register custom ones in <app>/templatetags/<module>.py, starting with register = template.Library(). Simple tags that just return a computed value use the @register.simple_tag decorator (optionally takes_context=True to access the current context), while tags needing to render a mini-template with their own logic use @register.inclusion_tag('partial.html'), which renders a specified template using the dictionary the function returns. Both must be loaded explicitly in any template that uses them via {% load <module> %} near the top of the file, after any {% extends %} line.
Cricket analogy: It's like a broadcaster building a custom graphic overlay — say a 'Manhattan chart' — that isn't a standard scoreboard element, registered once and then dropped into any match broadcast that needs it.
# blog/templatetags/blog_extras.py
from django import template
register = template.Library()
@register.simple_tag
def reading_time(word_count, wpm=200):
minutes = max(1, round(word_count / wpm))
return f'{minutes} min read'
@register.inclusion_tag('blog/partials/author_card.html')
def author_card(author):
return {'author': author, 'article_count': author.article_set.count()}
{# in a template #}
{% load blog_extras %}
{% reading_time article.word_count %}
{% author_card article.author %}Context Managers: `{% with %}` and RequestContext Internals
{% with total=items|length %}...{% endwith %} caches an expensive or repeated expression's result under a local name for the duration of the block, avoiding recomputation every time that expression is referenced in the template — useful when a filter chain or property access is non-trivial. Internally, RequestContext maintains context as a stack of dictionaries pushed and popped as template blocks and includes are entered and exited, which is why a variable set inside a {% for %} loop or {% with %} block doesn't leak out and shadow a same-named variable defined earlier in the template. Understanding this stack behavior matters when debugging why a variable appears unexpectedly unset or reset outside the block that defined it.
Cricket analogy: It's like a scorer caching the current run rate once per over instead of recalculating it after every single ball, then discarding that cached figure once the over ends.
{% load %} tags are per-template, not inherited automatically through {% extends %} — a child template that uses a custom tag must its own {% load %} line even if the parent template already loaded that same tag library.
Custom context processors run on every single template render that uses RequestContext across the entire project, so putting an expensive database query inside one (rather than in a specific view) silently adds that query's cost to every page load, including ones that never use the data.
- The template context merges view-supplied data with output from context processors (auth, request, messages, etc.).
- Context processors only apply to templates rendered via RequestContext, which render() and generic CBVs use by default.
- @register.simple_tag returns a computed value; @register.inclusion_tag renders a sub-template from a returned dict.
- Custom tags/filters live in <app>/templatetags/<module>.py and must be loaded per-template with {% load %}.
- {% with %}...{% endwith %} caches an expression's result under a local name for that block only.
- Context behaves as a stack: variables set inside {% for %} or {% with %} don't leak outside their block.
- Avoid expensive queries inside context processors since they run on every RequestContext-rendered page.
Practice what you learned
1. Why is {{ user }} available in nearly every Django template without the view explicitly passing it?
2. What decorator would you use to create a template tag that renders its own partial HTML template?
3. What happens to a variable set inside a {% with %} block once the block ends?
4. Why should you avoid expensive database queries inside a custom context processor?
Was this page helpful?
You May Also Like
Django Templates
Learn Django's built-in template language — variables, tags, filters, template inheritance, and how the template engine renders context into HTML safely.
Class-Based Views
Understand how Django's class-based views (CBVs) organize request handling into methods on a class, and how generic CBVs and mixins reduce boilerplate for common patterns like CRUD.
URL Routing in Django
Learn how Django maps incoming request paths to views using urlpatterns, path converters, included URLconfs, and named URLs for reversible linking.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentNext.js Study Notes
JavaScript · 30 topics