Regex Paths with re_path()
Converters cover most URLs. Now the cookbook wants a monthly archive: /recipes/archive/2025/09/. The year must be exactly four digits and the month exactly two. int would happily accept 7 or 123456. When you need a rule that precise, you can describe the URL with a regular expression.
The rule
re_path()matches a regex; named groups arrive as strings.
from django.urls import path, re_path
from . import views
urlpatterns = [
re_path(r"^archive/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.archive),
]
def archive(request, year, month):
# /recipes/archive/2025/09/ → year="2025", month="09"
...Read the pattern piece by piece:
r"..."is a raw string, so backslashes such as\dreach the regex engine untouched.^anchors the start of the remaining path,$anchors the end. Without$,archive/2025/09/anythingwould match too.[0-9]{4}means exactly four digits.(?P<year>...)is a named group: whatever it matches is passed as the keyword argumentyear.
The key difference from path(): no converters. Every captured value is a str, so the view converts with int(year) when it needs a number.
Two more rules. Use named groups rather than bare ( ) groups, so arguments arrive by name and cannot get swapped. And do not mix the two styles in one pattern; if any group is named, unnamed ones are ignored.
path() and re_path() can sit in the same urlpatterns list, and the usual first-match-wins order applies to both.
The shortcut
Reach for re_path() only when you can finish the sentence "it must be exactly …" and no converter says it. Otherwise path() is shorter, easier to read, and converts types for you. (A custom converter is the third option when the same rule is needed in many URLs.)
After include()
The app sees
archive/2025/09/.
The classic slip is forgetting $, and then a short pattern quietly matches much longer URLs.
Drills
Answer fast — trust the rule.
With re_path(r"^archive/(?P<year>[0-9]{4})/$", views.archive), what does the view receive for archive/2025/?
What does the $ at the end of a re_path() pattern do?
Which is a named group that passes month to the view?
You need /recipes/42/, any positive whole number. Which is the better choice?
Remember
re_path()matches a regex; named groups arrive as strings.- Use it only when "it must be exactly …" cannot be said with a converter.
- Trap: a missing
$lets longer URLs match.
