[Fixed]-Django raising 404 with a message


In general, 404 error is “page not found” error – it should not have customizable messages, simply because it should be raised only when a page is not found.

You can return a TemplateResponse with status parameter set to 404



Generally there should not be any custom messages in 404 errors bu if you want to implement it you can do this using django middlewares.


from django.http import Http404, HttpResponse

class Custom404Middleware(object):
    def process_exception(self, request, exception):
        if isinstance(exception, Http404):
            # implement your custom logic. You can send
            # http response with any template or message
            # here. unicode(exception) will give the custom
            # error message that was passed.
            msg = unicode(exception)
            return HttpResponse(msg, status=404)

Middlewares Settings

    # Uncomment the next line for simple clickjacking protection:
    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',

This will do the trick. Correct me if I am doing any thing wrong. Hope this helps.


Raise an Http404 exception inside a view. It’s usually done when you catch a DoesNotExist exception. For example:

from django.http import Http404

def article_view(request, slug):
        entry = Article.objects.get(slug=slug)
    except Article.DoesNotExist:
        raise Http404()
    return render(request, 'news/article.html', {'article': entry, })

Even better, use get_object_or_404 shortcut:

from django.shortcuts import get_object_or_404

def article_view(request):
    article = get_object_or_404(MyModel, pk=1)
    return render(request, 'news/article.html', {'article': entry, })

If you’d like to customize the default 404 Page not found response, put your own template called 404.html to the templates folder.


Yes we can show specific exception message when raise Http404.

Pass some exception message like this

raise Http404('Any kind of message ')

Add 404.html page into templates directory.




I figured out a solution for Django 2.2 (2019) after a lot of the middleware changed. It is very similar to Muhammed’s answer from 2013. So here it is:


from django.http import Http404, HttpResponse

class CustomHTTP404Middleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before the view (and later middleware) are called.
        response = self.get_response(request)
        # Code to be executed for each request/response after the view is called.
        return response

    def process_exception(self, request, exception):
        if isinstance(exception, Http404):
            message = f"""
                User: {request.user},
                Referrer: {request.META.get('HTTP_REFERRER', 'no referrer')}
            exception.args = (message,)

Also, add this last to your middleware in settings.py: 'app.middleware.http404.CustomHTTP404Middleware',


if you want to raise some sort of static messages for a particular view , you can do as follows:-

from django.http import Http404

def my_view(request):
  raise Http404("The link seems to be broken")


You can return a plain HttpResponse object with a status code (in this case 404)

from django.shortcuts import render_to_response

def my_view(request):
    template_context = {}

    # ... some code that leads to a custom 404

    return render_to_response("my_template.html", template_context, status=404)


In my case, I wanted to take some action (e.g. logging) before returning a custom 404 page. Here is the 404 handler that does it.

def my_handler404(request, exception):
    logger.info(f'404-not-found for user {request.user} on url {request.path}')
    return HttpResponseNotFound(render(request, "shared/404.html"))

Note that HttpResponseNotFound is required. Otherwise, the response’s HTTP status code is 200.


The default 404 handler calls 404.html . You could edit that if you don’t need anything fancy or can override the 404 handler by setting the handler404 view — see more here

Leave a comment