Django Page Not Found (404): Complete Guide to Understanding and Handling 404 Errors

Last updated 1 month, 2 weeks ago | 132 views 75     5

Tags:- Python Django

In web development, a 404 error means the server couldn’t find what was requested. Django, like most web frameworks, handles this scenario with a "Page Not Found" response. Understanding how Django manages 404 errors — and how you can customize them — is key to creating a polished and user-friendly application.


What is a 404 Error?

A 404 (Not Found) HTTP response means:

"The page you’re trying to access does not exist on the server."

This could happen because:

  • A user visits a non-existent URL

  • A link is broken or mistyped

  • A resource (like a blog post or user) was deleted or never existed


⚙️ How Django Handles 404 by Default

By default, Django returns a plain and simple HTML page when a 404 error occurs. The view function doesn't need to explicitly raise it unless you're manually checking conditions.

Example: Auto-generated 404

# No matching URL pattern for this path
http://localhost:8000/does-not-exist/

If the URL doesn’t match any pattern in urls.py, Django automatically raises a Http404 and shows a default page.


Manually Raising 404 in Views

Sometimes you want to raise a 404 manually if a specific object doesn’t exist. Django makes this easy:

Using get_object_or_404 (Recommended)

from django.shortcuts import get_object_or_404
from .models import Article

def article_detail(request, slug):
    article = get_object_or_404(Article, slug=slug)
    return render(request, 'article_detail.html', {'article': article})

Manually Raising Http404

from django.http import Http404

def article_detail(request, slug):
    try:
        article = Article.objects.get(slug=slug)
    except Article.DoesNotExist:
        raise Http404("Article not found")
    return render(request, 'article_detail.html', {'article': article})

Customizing the 404 Page

You can create a custom 404.html to show a styled error page instead of Django’s default.

Step-by-Step:

1. Create 404.html in your main template directory:

templates/404.html:

<!DOCTYPE html>
<html>
<head>
    <title>Page Not Found - 404</title>
</head>
<body>
    <h1>Oops! Page not found (404)</h1>
    <p>The page you were looking for doesn’t exist or has been moved.</p>
    <a href="/">Go to Homepage</a>
</body>
</html>

2. Ensure DEBUG = False and ALLOWED_HOSTS is set properly in settings.py:

DEBUG = False

ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'yourdomain.com']

⚠️ Custom error pages only appear when DEBUG = False. Otherwise, Django will show a detailed traceback (for developers).

3. Run with production settings

To test:

python manage.py runserver --insecure

Then visit a non-existent URL to see your custom 404 page.


Best Practices for 404 Pages

  • Add navigation links back to home or help pages

  • Use branding consistent with your site

  • Explain possible reasons (broken link, moved page)

  • Log errors for analysis (especially if 404s are frequent)


Debugging and Fixing Common 404 Errors

Scenario Cause Fix
URL not found No matching pattern in urls.py Check and update URL patterns
Mistyped slug or ID Invalid path or query Use get_object_or_404()
Static files 404 Static files not found in production Ensure collectstatic is run and paths are correct
DEBUG = True shows Django error page That’s expected Set DEBUG = False to test custom 404 page
Wrong ALLOWED_HOSTS 404 or 400 errors Set ALLOWED_HOSTS in production

Example: Complete Custom 404 Setup

settings.py

DEBUG = False
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

templates/404.html

{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>404 Not Found</title>
    <link rel="stylesheet" href="{% static 'css/error.css' %}">
</head>
<body>
    <div class="error-page">
        <h1>404</h1>
        <p>Sorry, we couldn’t find that page.</p>
        <a href="/">Return to homepage</a>
    </div>
</body>
</html>

urls.py

from django.contrib import admin
from django.urls import path, include

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

Extra: Logging 404 Errors

To track 404 errors in production, you can enable logging:

# settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'WARNING',
            'class': 'logging.FileHandler',
            'filename': 'django.log',
        },
    },
    'loggers': {
        'django.request': {
            'handlers': ['file'],
            'level': 'WARNING',
            'propagate': True,
        },
    },
}

Summary

Feature Description
404 error Raised when a page or object isn’t found
Default behavior Django returns a generic 404 page
Custom page Add 404.html in your template directory
Manual 404 Use get_object_or_404() or raise Http404()
Production display Set DEBUG = False and configure ALLOWED_HOSTS

❓ Bonus: Want Custom 403 or 500 Pages?

You can also create:

  • 403.html for forbidden access

  • 500.html for server errors

Same rules apply: DEBUG = False and place them in the root templates folder.