9

I have a website where some pages are edited by hand. When one of those templates is missing, it just means that the page is not present, so I would like to display an Error 404.

Instead I get an exception TemplateDoesNotExist.

Is there a way to tell Django to display an error 404 whenever it does not find a template?

Andrea
  • 20,253
  • 23
  • 114
  • 183

3 Answers3

13

If you want this behaviour for all views on your site, you might want to write your own middleware with a process_exception method.

from django.template import TemplateDoesNotExist
from django.views.defaults import page_not_found

class TemplateDoesNotExistMiddleware(object):
    """ 
    If this is enabled, the middleware will catch
    TemplateDoesNotExist exceptions, and return a 404
    response.
    """

    def process_exception(self, request, exception):
        if isinstance(exception, TemplateDoesNotExist):
            return page_not_found(request)

If you have defined your own handler404 you would need to replace page_not_found above. I'm not immediately sure how you could convert the string handler404 into the callable required in the middleware..

To enable your middleware, add it to MIDDLEWARE_CLASSES in settings.py. Be careful of the position where you add it. The standard Django middleware warning applies:

Again, middleware are run in reverse order during the response phase, which includes process_exception. If an exception middleware returns a response, the middleware classes above that middleware will not be called at all.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
9

put the return of the response in the view (or whereever the template is rendered) in a try-except block:

from django.http import Http404
from django.shortcuts import render_to_response
from django.template import TemplateDoesNotExist

def the_view(request):
    ...
    try:
        return render_to_response(...)
    except TemplateDoesNotExist:
        raise Http404
Torsten Engelbrecht
  • 13,318
  • 4
  • 46
  • 48
  • Need to import the exception: `from django.template import TemplateDoesNotExist`. – Daniel Roseman May 08 '11 at 11:20
  • Thanks for the addition. I forget where to import the exception from, since couldn't check. Edited the answer. – Torsten Engelbrecht May 08 '11 at 11:47
  • Yes, I know I can do this, but it becomes some boilerplate in al views. I hoped there was a global way to do this. – Andrea May 08 '11 at 12:58
  • If you want to avoid boilerplate, define a function `my_render_to_response` which encapsulates the `try..except` block. Then use `my_render_to_response` in your views instead of render_to_response. – Alasdair May 08 '11 at 14:55
-1

Off the top of my head, but if you set DEBUG=False in your settings, won't you get a 404 then on every error (including TemplateNotFound)?

Mathieu Dhondt
  • 8,405
  • 5
  • 37
  • 58
  • I think so, but I need this for testing. – Andrea May 08 '11 at 19:34
  • 2
    This answer is incorrect. For errors the default Django behaviour is to run the `server_error` view, will render the `500.html` template and return a page with error code 500. See http://docs.djangoproject.com/en/dev/topics/http/views/#the-500-server-error-view – Alasdair May 08 '11 at 19:46