28

According to the documentation this should be fairly simple: I just need to define handler404. Currently I am doing, in my top urls.py:

urlpatterns = [
    ...
]

handler404 = 'myapp.views.handle_page_not_found'

The application is installed. The corresponding view is just (for the time being I just want to redirect to the homepage in case of 404):

def handle_page_not_found(request):
    return redirect('homepage')

But this has no effect: the standard (debug) 404 page is shown.

The documentation is a bit ambiguous:

  • where should handler404 be defined? The documentation says in the URLconf but, where exactly? I have several applications, each with a different urls.py. Can I put it in any of them? In the top URLconf? Why? Where is this documented?
  • what will be catched by this handler? Will it catch django.http.Http404, django.http.HttpResponseNotFound, django.http.HttpResponse (with status=404)?
blueFast
  • 41,341
  • 63
  • 198
  • 344
  • 4
    What's `DEBUG` in your settings? If it's `True`, can you change it to `False` and see? – Shang Wang Feb 02 '16 at 14:32
  • 1
    @ShangWang: thanks! Indeed, setting it to `False` solves the problem. This is not documented, afaik. – blueFast Feb 02 '16 at 14:38
  • 1
    @delavnog - Its in the [error reporting sections](https://docs.djangoproject.com/en/1.9/howto/error-reporting/#error-reporting) - "When DEBUG is False,..." – Sayse Feb 02 '16 at 14:42
  • @Sayse: in a completely different context (Email reports, ...), and not related to error handlers. It would make more sense to mention this in the corresponding paragraph, but I digress ... – blueFast Feb 02 '16 at 14:46
  • @delavnog - I was just more pointing out that it does mention that it mentions it there, it hints at it under the section in settings for [debug](https://docs.djangoproject.com/en/1.9/ref/settings/#debug) about how it handles error pages, and there are lots of other references to `DEBUG` throughout :) – Sayse Feb 02 '16 at 14:49
  • @Sayse today's moment of unintended comedy: 6 years later and that link leads to, appropriately, a 404 error :D – Nathaniel Hoyt Oct 26 '22 at 17:06

4 Answers4

19

As we discussed, your setup is correct, but in settings.py you should make DEBUG=False. It's more of a production feature and won't work in development environment(unless you have DEBUG=False in dev machine of course).

Shang Wang
  • 24,909
  • 20
  • 73
  • 94
12

All the other answers were not up to date. Here's what worked for me in Django 3.1:

urls.py

from django.conf.urls import handler404, handler500, handler403, handler400
from your_app_name import views

handler404 = views.error_404
handler500 = views.error_500

views.py

def error_404(request, exception):
   context = {}
   return render(request,'admin/404.html', context)

def error_500(request):
   context = {}
   return render(request,'admin/500.html', context)

Note, you will have to edit this code to reflect your app name in the import statement in urls.py and the path to your html templates in views.py.

devdrc
  • 1,853
  • 16
  • 21
  • If you have a TemplateView? ```index_view = never_cache(TemplateView.as_view(template_name='index.html')) ``` Why you could not do `return index` inside `error_404` function? – realnot Nov 12 '20 at 12:34
  • @realnot - Perhaps you could. Did you try? There are often more than one way to solve a problem. – devdrc Nov 13 '20 at 18:30
  • I solved. `def error_404(request, exception): return index_view(request)`. `index_view` is a template that return a template response, you have to pass a request. +1 for your suggestion. Is the correct one! – realnot Nov 14 '20 at 09:08
  • in `urls.py` change `handler404 = views.error_404` to `urls.handler404 = views.error_404` and import urls as follow `from django.conf import urls` – Hajras El Gdiry HG Nov 30 '20 at 10:05
  • @HajrasElGdiryHG Simply to be more explicit? – devdrc Nov 30 '20 at 17:41
11

Debug should be False and add to view *args and **kwargs. Add to urls.py handler404 = 'view_404'

def view_404(request, *args, **kwargs):
return redirect('https://your-site/404')

If I didn't add args and kwargs server get 500.

Pasha M
  • 221
  • 3
  • 5
5

To render 404 Error responses on a custom page, do the following:

In your project directory open settings.py and modify DEBUG as follows:

    DEBUG = False

In the same directory create a file and name it views.py, insert the following code:

   from django.shortcuts import render

   def handler404(request, exception):
       return render(request, 'shop/shop.html')

Finally open urls.py file which is in the same project directory and add the following code:

   from django.contrib import admin
   from . import views

   handler404 = views.handler404

   urlpatterns = [
      path('admin/', admin.site.urls),
   ]
GilbertS
  • 591
  • 8
  • 12