πΊοΈ Django URL Routing: Your Websiteβs GPS System
The Big Picture: What Are URLs Really?
Imagine youβre building a giant treasure map for your website. Every treasure (page) needs its own special path. When someone types a web address, Django acts like a smart GPS that reads the address and takes them to the right treasure!
Real Life Example:
- You type:
www.pizzashop.com/menu - Django reads
/menuand thinks: βAha! They want to see the menu!β - Django shows you the menu page π
π URLs and URL Patterns
Whatβs a URL Pattern?
A URL pattern is like a secret code that Django understands. It tells Django: βWhen someone visits THIS address, show them THAT page.β
# Like a recipe card for your website!
path('hello/', views.say_hello)
Breaking it down:
'hello/'= the address people typeviews.say_hello= the function that runs
Simple Analogy πͺ
Think of a restaurant:
- Customer says: βI want pizza!β β URL:
/pizza/ - Waiter knows to go to the pizza chef β View:
make_pizza
π URL Configuration File (urls.py)
Your Websiteβs Address Book
Every Django project has a special file called urls.py. Itβs like a big phone book that lists all the addresses and who answers at each one!
# myproject/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home),
path('about/', views.about),
path('contact/', views.contact),
]
Whatβs happening here:
urlpatterns= a list of all addressespath('', views.home)= homepage (nothing after /)path('about/', views.about)= the about page
π Project Structure
myproject/
βββ myproject/
β βββ urls.py β Main address book
βββ blog/
β βββ urls.py β Blog's own address book
βββ shop/
βββ urls.py β Shop's own address book
π€οΈ path() and re_path() Functions
path() - The Easy One π―
Use path() for simple, clean addresses:
from django.urls import path
path('products/', views.product_list)
path('products/shoes/', views.shoes)
re_path() - The Power Tool π§
Use re_path() when you need super-specific patterns using regular expressions:
from django.urls import re_path
# Match any year from 2000-2099
re_path(r'^year/(?P<year>[0-9]{4})/#x27;, views.year_view)
When to Use Which?
Use path() when⦠|
Use re_path() when⦠|
|---|---|
| Simple addresses | Complex patterns |
| Easy to read | Need regex power |
| Most cases! | Specific formats |
π·οΈ URL Namespacing and Reversing
The Problem π€
Imagine you have two apps, both with a page called βlistβ:
- Blog has
/list/for blog posts - Shop has
/list/for products
How does Django know which one you mean?
The Solution: Namespaces! πͺ
# blog/urls.py
app_name = 'blog' # β This is the namespace!
urlpatterns = [
path('list/', views.post_list, name='list'),
]
# shop/urls.py
app_name = 'shop'
urlpatterns = [
path('list/', views.product_list, name='list'),
]
Reversing URLs π
Instead of typing URLs directly, let Django figure them out:
from django.urls import reverse
# Get the blog list URL
url = reverse('blog:list') # Returns '/blog/list/'
# Get the shop list URL
url = reverse('shop:list') # Returns '/shop/list/'
In Templates:
<a href="{% url 'blog:list' %}">See all posts</a>
π URL include() Function
Why Include?
Imagine a big company with departments:
- Marketing handles their own stuff
- Engineering handles their own stuff
- HR handles their own stuff
Each department has their own internal phone directory!
How It Works
# Main urls.py (The CEO's directory)
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls')),
path('shop/', include('shop.urls')),
path('users/', include('users.urls')),
]
Now:
/blog/anythingβ handled by blog app/shop/anythingβ handled by shop app/users/anythingβ handled by users app
Benefits π
- Organized - Each app manages its own URLs
- Reusable - Move apps between projects easily
- Clean - Main file stays small and readable
π’ URL Parameters and Converters
Catching Information from URLs
Sometimes URLs carry extra info, like asking for a specific item:
/products/42/ β I want product #42!
/users/john/ β Show me John's profile!
Basic Parameters
# Capture a number
path('products/<int:id>/', views.product_detail)
# Capture text
path('users/<str:username>/', views.user_profile)
Built-in Converters π¦
| Converter | What It Catches | Example |
|---|---|---|
str |
Any text (no /) | hello |
int |
Numbers only | 42 |
slug |
Letters, numbers, - _ | my-post |
uuid |
Unique IDs | abc123... |
path |
Any text (with /) | a/b/c |
Using Parameters in Views
def product_detail(request, id):
# id is automatically passed in!
product = Product.objects.get(id=id)
return render(request, 'product.html',
{'product': product})
Multiple Parameters
# Year, month, day in one URL!
path('archive/<int:year>/<int:month>/<int:day>/',
views.archive_view)
# URL: /archive/2024/12/25/
# year=2024, month=12, day=25
π¨ Custom Error Pages
The Default Problem
When something goes wrong, Django shows ugly error pages. Letβs make them pretty!
Common Error Codes
| Code | Name | When It Happens |
|---|---|---|
| 400 | Bad Request | Somethingβs wrong with the request |
| 403 | Forbidden | Not allowed to see this |
| 404 | Not Found | Page doesnβt exist |
| 500 | Server Error | Something broke on our end |
Creating Custom Error Pages
Step 1: Create templates in your templates folder:
templates/
βββ 400.html
βββ 403.html
βββ 404.html
βββ 500.html
Step 2: Add handlers in your main urls.py:
# myproject/urls.py
from django.conf.urls import handler400, handler403
from django.conf.urls import handler404, handler500
handler400 = 'myapp.views.bad_request'
handler403 = 'myapp.views.permission_denied'
handler404 = 'myapp.views.page_not_found'
handler500 = 'myapp.views.server_error'
Step 3: Create the views:
# myapp/views.py
def page_not_found(request, exception):
return render(request, '404.html', status=404)
def server_error(request):
return render(request, '500.html', status=500)
Example 404 Template
<!-- templates/404.html -->
<!DOCTYPE html>
<html>
<head>
<title>Oops! Page Not Found</title>
</head>
<body>
<h1>π We can't find that page!</h1>
<p>The page you're looking for
doesn't exist.</p>
<a href="/">Go Home</a>
</body>
</html>
π― Quick Summary
graph TD A[User Types URL] --> B[Django URLs.py] B --> C{Match Found?} C -->|Yes| D[Run the View] C -->|No| E[Show 404 Page] D --> F[Return Response]
The URL Routing Journey:
- User visits β
/products/shoes/ - Django checks β urlpatterns list
- Match found β
path('products/shoes/', views.shoes) - View runs β
shoes()function executes - Page shown β User sees the shoes page!
π Pro Tips
-
Always use names for your URLs:
path('about/', views.about, name='about') -
Use namespaces to avoid conflicts:
app_name = 'myapp' -
Keep main urls.py clean with
include():path('blog/', include('blog.urls')) -
Validate parameters with converters:
path('post/<int:id>/', views.post) -
Create friendly error pages for better UX!
π You Did It!
Now you understand how Djangoβs URL routing works - itβs just a smart GPS system for your website! Every URL pattern is a direction, every view is a destination, and Django is the helpful guide making sure everyone gets where they need to go.
Remember: URLs are how users find things on your site. Make them clean, logical, and memorable! π