Django URLs

Django URLs map incoming web requests to the Python functions or classes that handle them, using a urls.py file and the path() function.

The Project URLconf

Every Django project has a ROOT_URLCONF setting pointing at a Python module - by convention called urls.py - that defines a list named urlpatterns. When a request comes in, Django walks this list from top to bottom and uses the first pattern that matches the request path.

Example

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('about/', views.about, name='about'),
]

The path() Function

path(route, view, kwargs=None, name=None) ties a URL pattern to a view. route is a string pattern matched against the request path (Django already strips the domain and leading slash for you), view is the callable that handles matching requests, and name lets you refer to this URL from templates and other Python code without hardcoding the string.

  • str - matches any non-empty string, excluding the / character
  • int - matches zero or any positive integer
  • slug - matches slug strings: ASCII letters, numbers, hyphens and underscores
  • uuid - matches a formatted UUID, e.g. 075194d3-6885-417e-a8a8-6c931e272f00
  • path - matches any non-empty string, including the / character

Example

# urls.py
path('article/<int:article_id>/', views.article_detail, name='article_detail')

# views.py
def article_detail(request, article_id):
    # article_id arrives as a Python int, not a string
    ...
ConverterMatchesExample
strAny non-empty string without /<str:username>
intZero or positive integers<int:id>
slugLetters, numbers, hyphens, underscores<slug:post_slug>
uuidA formatted UUID<uuid:token>
pathAny string, including /<path:resource>
Note: Always give your URL patterns a name=, even if you don't need it yet. Referencing URLs by name instead of a hardcoded string keeps templates and redirects working even if the route itself changes later.

Including Other URLconfs

As a project grows, it's common to keep each app's routes in its own urls.py and pull them into the project with include(). This keeps routing modular - an app's URLs can be reused or moved without editing the project-level file.

Example

# project/urls.py
from django.urls import include, path

urlpatterns = [
    path('blog/', include('blog.urls')),
]

# blog/urls.py
from django.urls import path
from . import views

app_name = 'blog'
urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('<int:pk>/', views.post_detail, name='post_detail'),
]

Exercise: Django URLs

How does Django decide which view handles an incoming request?