Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
The Request–Response Flow  ›  Lesson

Named URLs and reverse()

Named URLs 15 minGiving a URL pattern a name lets templates and Python code build its address with the url tag or reverse(), so links keep working when the route text changes.

Named URLs and reverse()

The cookbook links to recipe pages from the home page, the search results, emails and a redirect after saving a form. If each link is typed as "/recipes/" + slug + "/", then the day someone moves recipes to a new URL, you hunt through the whole project for strings. Named URLs make the pattern list the only place an address is written.

The rule

Name the pattern once; build every link from the name.

Give the app a namespace and each pattern a name:

# recipes/urls.py
app_name = "recipes"

urlpatterns = [
    path("", views.recipe_list, name="list"),
    path("<slug:slug>/", views.recipe_detail, name="detail"),
]

The full name is namespace:name, here recipes:detail. The namespace keeps it apart from a detail in another app, such as reviews:detail.

In templates, the url tag builds the address:

<a href="{% url 'recipes:detail' recipe.slug %}">{{ recipe.title }}</a>
<a href="{% url 'recipes:detail' slug=recipe.slug %}">same link, by keyword</a>

In Python, reverse() does the same job:

from django.shortcuts import redirect
from django.urls import reverse

reverse("recipes:list")                                    # "/recipes/"
reverse("recipes:detail", kwargs={"slug": "tomato-soup"})  # "/recipes/tomato-soup/"

return redirect("recipes:detail", slug=recipe.slug)        # after saving a form

Matching goes URL → view. Reversing goes the other way: name + arguments → URL. It includes the prefix from include(), so the app never needs to know where it is mounted.

One wrinkle: a class attribute is evaluated when the module is imported, before the URL patterns are loaded. There, use reverse_lazy("recipes:list"), which waits until the value is actually used.

If the name is misspelled or a required argument is missing, Django raises NoReverseMatch. That is a feature: a broken link fails loudly during development instead of silently sending readers to a 404.

The shortcut

Whenever you are about to type a / inside a link or redirect, stop and write the name instead. A hard-coded path in a template or view is a bug waiting for the next URL change.

Moving recipe pages to /recipes/view/<slug>/Step 1 of 4
  1. Change one route

    path("view/<slug:slug>/", views.recipe_detail, name="detail").

Drills

Answer fast — trust the rule.

quick drill

With app_name = "recipes" and name="detail", how do you refer to the pattern?

quick drill

What does reverse("recipes:detail", kwargs={"slug": "ragu"}) return?

quick drill

A template uses {% url 'recipes:detail' %} but the pattern needs a slug. What happens?

quick drill

Where should you use reverse_lazy() instead of reverse()?

Remember

  • Name the pattern once; build every link from the name.
  • {% url %} in templates, reverse() or redirect() in Python, reverse_lazy() in class attributes.
  • Trap: typing / into a link instead of a name.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainRename the route, keep the links

The team wants recipe pages to move from /recipes// to /recipes/view//. Explain how naming the URL pattern and using {% url %} and reverse() means this change touches only one line. Include the app_name, the pattern, one template link and one Python use.