Django · Lesson 3 of 5
Views, URLs and Templates
Route a URL to a view and render HTML with the template language.
- Beginner
- 17 min read
- 3 objectives
Before this lessonLesson 2: Models and Migrations
What you will learn
- Write function views
- Map URLs
- Use template tags and filters
When a browser asks for a page, Django looks up the URL in your URL configuration, calls the matching view, and sends back the response the view returns.
A view
# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_list(request):
posts = Post.objects.filter(published=True).select_related("author")
return render(request, "blog/post_list.html", {"posts": posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk, published=True)
return render(request, "blog/post_detail.html", {"post": post})render combines a template with a context dictionary. get_object_or_404 returns the object or an HTTP 404 page, instead of crashing with an exception.
URLs
# blog/urls.py
from django.urls import path
from . import views
app_name = "blog"
urlpatterns = [
path("", views.post_list, name="list"),
path("<int:pk>/", views.post_detail, name="detail"),
]
# mysite/urls.py
from django.urls import include, path
urlpatterns = [
path("blog/", include("blog.urls")),
]<int:pk> captures a number from the URL and passes it to the view as pk. Giving each route a name lets you generate links without hard-coding paths.
Templates
Create blog/templates/blog/post_list.html. Templates use {{ variable }} to print values and {% tag %} for logic.
<!-- blog/templates/blog/post_list.html -->
{% extends "base.html" %}
{% block content %}
<h1>Posts</h1>
{% for post in posts %}
<article>
<h2><a href="{% url 'blog:detail' post.pk %}">{{ post.title }}</a></h2>
<p>by {{ post.author.name }} on {{ post.created|date:"M d, Y" }}</p>
<p>{{ post.body|truncatewords:30 }}</p>
</article>
{% empty %}
<p>No posts yet.</p>
{% endfor %}
{% endblock %}{% extends %}and{% block %}: inherit a shared layout so you write headers and footers once.|date,|truncatewords: filters that transform values.- Django auto-escapes variables, protecting against XSS. Only use
|safeon content you fully trust.
Class-based views
For common patterns, generic views remove boilerplate.
from django.views.generic import ListView, DetailView
class PostList(ListView):
model = Post
queryset = Post.objects.filter(published=True)
template_name = "blog/post_list.html"
context_object_name = "posts"
paginate_by = 10# Write your solution here
