Rendering templates: connecting a view to HTML
HttpResponse("some string") was enough to prove the routing works — real pages need actual HTML. This part is deliberately brief on template syntax; the standalone Django template views tutorial is the full reference for {% %} tags, filters, and inheritance in depth. Here, it's just wired into the blog project.
The app's templates folder
blog/
templates/
blog/
base.html
post_list.htmlDjango looks for templates inside a templates/ folder on each installed app's own path — the blog/ folder nested inside templates/ is a namespacing convention (covered fully in the standalone tutorial), and skipping it is what causes two apps that both have a post_list.html to silently collide.
A base layout
{# blog/templates/blog/base.html #}
<!DOCTYPE html>
<html>
<head><title>{% block title %}My Blog{% endblock %}</title></head>
<body>
<header><h1><a href="/">My Blog</a></h1></header>
<main>{% block content %}{% endblock %}</main>
</body>
</html>Every template this series adds from here on extends this one file — the header, the <!DOCTYPE>, the overall shell only ever gets written once.
Rendering the post list
# blog/views.py
from django.shortcuts import render
def post_list(request):
return render(request, "blog/post_list.html"){# blog/templates/blog/post_list.html #}
{% extends "blog/base.html" %}
{% block title %}Latest posts{% endblock %}
{% block content %}
<p>Posts will render here once there's a Post model to query.</p>
{% endblock %}render() replaces the raw HttpResponse from part 3 — it loads the template, renders it, and wraps the result in a response, in one call. Refresh http://127.0.0.1:8000/ and the base layout now renders around the placeholder text.
FAQ
How does Django find blog/post_list.html from just that string in render()?
It searches every installed app's templates/ folder for a matching path, in the order apps are listed in INSTALLED_APPS — the blog/ prefix inside the templates folder (part of this page's namespacing convention) is what's being matched, not a literal filesystem path relative to the project root.
Can I pass data into a template from the view?
Yes — render(request, "blog/post_list.html", {"posts": some_queryset}) is the pattern; the dict's keys become variables usable inside the template with {{ posts }}. This part skips it only because there's no Post model to query yet — the very next part adds one.
Where do CSS and images go, since there's no mention of them here?
Static files (CSS, JavaScript, images) use a separate system from templates — a static/ folder per app plus Django's {% load static %} template tag — deliberately out of scope for this part, which is focused on the render pipeline itself.
Next: an actual Post model, so this page has real data to loop over instead of placeholder text.