Django URLs

Routing requests to the right views

🔗 What are Django URLs?

Django URLs map web addresses to view functions. The URL dispatcher examines the requested URL and calls the appropriate view. This routing system keeps your application organized and URLs clean.

path('blog/', views.blog_home)

URL Components

🛤️

Path

Define URL patterns

path('home/', views.home)
🎯

Parameters

Capture URL values

path('post/<int:id>/', views.detail)
🏷️

Names

Reference URLs by name

path('about/', views.about, name='about')
📦

Include

Organize app URLs

path('blog/', include('blog.urls'))

🔹 Basic URL Configuration

URL patterns are defined in urls.py files. The main project urls.py routes to app-specific URL configurations for better organization.

🔸 Project URLs (mysite/urls.py)

# mysite/urls.py
from django.contrib import admin
from django.urls import path, include

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

🔸 App URLs (blog/urls.py)

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

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

URL Mapping:

/blog/ → post_list view

/blog/about/ → about view

/blog/contact/ → contact view

🔹 URL Parameters

Capture dynamic values from URLs using path converters. These values are passed as arguments to your view functions.

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

urlpatterns = [
    # Integer parameter
    path('post/<int:pk>/', views.post_detail, name='post_detail'),
    
    # String parameter
    path('category/<str:name>/', views.category, name='category'),
    
    # Slug parameter
    path('article/<slug:slug>/', views.article, name='article'),
]
# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post

def post_detail(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return render(request, 'blog/post_detail.html', {'post': post})

def category(request, name):
    posts = Post.objects.filter(category=name)
    return render(request, 'blog/category.html', {'posts': posts, 'category': name})

Common Path Converters:

  • int: Matches integers (e.g., 1, 42, 999)
  • str: Matches any non-empty string (excluding /)
  • slug: Matches slugs (letters, numbers, hyphens, underscores)
  • uuid: Matches UUID formatted strings
  • path: Matches any string (including /)

🔹 Named URLs

Naming URLs allows you to reference them in templates and views without hardcoding paths. This makes your code more maintainable.

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

app_name = 'blog'  # Namespace for this app

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

🔸 Using Named URLs in Templates

<!-- templates/blog/post_list.html -->
<a href="{% url 'blog:post_list' %}">All Posts</a>
<a href="{% url 'blog:post_detail' pk=post.id %}">Read More</a>
<a href="{% url 'blog:post_create' %}">Create New Post</a>

🔸 Using Named URLs in Views

# blog/views.py
from django.shortcuts import redirect
from django.urls import reverse

def create_post(request):
    if request.method == 'POST':
        # Create post logic
        return redirect('blog:post_list')
    
    # Or use reverse() to get URL string
    url = reverse('blog:post_detail', kwargs={'pk': 5})
    return redirect(url)

🔹 Including App URLs

Use include() to reference other URL configurations. This keeps your project organized by separating app-specific URLs.

# mysite/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
    path('shop/', include('shop.urls')),
    path('users/', include('users.urls')),
    path('', include('home.urls')),
]
# blog/urls.py
from django.urls import path
from . import views

app_name = 'blog'

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

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

app_name = 'shop'

urlpatterns = [
    path('', views.shop_home, name='home'),
    path('products/', views.product_list, name='product_list'),
]

🔹 Regular Expression URLs

For complex URL patterns, use re_path() with regular expressions. This provides more flexibility than simple path converters.

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

urlpatterns = [
    # Match year/month/day format
    re_path(r'^archive/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', 
            views.archive, 
            name='archive'),
    
    # Match specific pattern
    re_path(r'^post/(?P<slug>[\w-]+)/$', 
            views.post_by_slug, 
            name='post_by_slug'),
]
# blog/views.py
def archive(request, year, month):
    posts = Post.objects.filter(
        published_date__year=year,
        published_date__month=month
    )
    return render(request, 'blog/archive.html', {
        'posts': posts,
        'year': year,
        'month': month
    })

🔹 URL Query Parameters

Access query parameters (e.g., ?page=2&sort=date) using request.GET in your views:

# blog/views.py
def post_list(request):
    # Get query parameters
    page = request.GET.get('page', 1)
    sort = request.GET.get('sort', 'date')
    search = request.GET.get('q', '')
    
    posts = Post.objects.all()
    
    # Filter based on search
    if search:
        posts = posts.filter(title__icontains=search)
    
    # Sort posts
    if sort == 'title':
        posts = posts.order_by('title')
    else:
        posts = posts.order_by('-published_date')
    
    return render(request, 'blog/post_list.html', {
        'posts': posts,
        'search': search,
        'sort': sort
    })
<!-- Example URLs -->
<a href="{% url 'post_list' %}?sort=title">Sort by Title</a>
<a href="{% url 'post_list' %}?sort=date">Sort by Date</a>

<form method="get">
    <input type="text" name="q" placeholder="Search...">
    <button type="submit">Search</button>
</form>

🔹 Error Handling URLs

Django provides default error pages, but you can customize them by creating specific views and templates:

# mysite/urls.py
from django.contrib import admin
from django.urls import path, include

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

# Custom error handlers
handler404 = 'blog.views.custom_404'
handler500 = 'blog.views.custom_500'
# blog/views.py
from django.shortcuts import render

def custom_404(request, exception):
    return render(request, 'errors/404.html', status=404)

def custom_500(request):
    return render(request, 'errors/500.html', status=500)

🔹 Best Practices

Follow these guidelines for clean and maintainable URL configurations:

  • Use app namespaces: Set app_name in each app's urls.py
  • Name all URLs: Always provide a name parameter
  • Keep URLs simple: Use clear, readable URL patterns
  • Organize by app: Each app should have its own urls.py
  • Use trailing slashes: Django convention is to include them
  • Avoid hardcoding: Use {% url %} and reverse() instead

🧠 Test Your Knowledge

Which function is used to include app URLs in the main urls.py?