URLs with parameters: primary keys, slugs, and get_object_or_404
{% url 'post_detail' post.slug %} from part 9 already assumes a URL pattern that takes a value — this part defines it, and points DetailView at the slug field instead of the numeric ID every model gets by default.
Capturing a value in the path
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.PostListView.as_view(), name="post_list"),
path("post/<slug:slug>/", views.PostDetailView.as_view(), name="post_detail"),
]<slug:slug> is a path converter: slug before the colon is the converter type (matches letters, numbers, hyphens, and underscores — exactly what SlugField produces), and slug after it is the keyword argument name the matched value gets passed to the view as. The other built-in converters worth knowing: <int:pk> for a numeric ID, <str:name> for any non-slash string, <uuid:id> for a UUID.
Pointing DetailView at the slug
# blog/views.py
class PostDetailView(DetailView):
model = Post
template_name = "blog/post_detail.html"
context_object_name = "post"
slug_field = "slug"
slug_url_kwarg = "slug"By default, DetailView expects a pk URL keyword and looks up Post.objects.get(pk=pk). slug_field tells it which model field to query against, and slug_url_kwarg tells it which URL keyword argument to read the value from — here, both happen to be named slug, which is the common case and also why Django's defaults for these two settings are already "slug" when omitted. They're shown explicitly here once, since knowing they exist is what makes a mismatched field/URL name debuggable instead of mysterious.
Why a slug instead of a numeric ID
/post/7/ vs. /post/my-first-post/Both work identically as far as Django's routing is concerned. The difference is entirely for the humans and search engines reading the URL: a slug says what the page is about before the page even loads, and it's what actually shows up in a shared link or a Google result — an opaque /post/7/ tells a reader nothing.
Changing a post's slug after publishing without redirecting the old URL. Every link anyone shared, bookmarked, or ranked in a search result now points at a 404 — treat a published slug as effectively permanent, or add a redirect from the old value if it truly has to change.
Next: Comment — a second model, linked to Post by a relationship, and what querying across that link actually looks like.