Custom 404 problem?

While not specifying a custom 404 handler, I get 404 thrown after trying to visit a wrong URL. After specifying a custom 404 handler, I get a 500 error for visiting the same URL. At this point I don’t know how to troubleshoot this because it only runs in production mode.

urls.py:

handler404 = 'infra.views.infra_404'

urlpatterns = [
    path('admin/', admin.site.urls, name='admin'),
    path('', infra_homepage, name='home'),
    # path('members/', include('django.contrib.auth.urls')),
    path('members/', include('members.urls')),
    path('track/', include('track.urls')),
]

views.py:

def infra_404(request, e=None):
    print(404)
    messages.error(request, '404: Page does not exist')
    return redirect('home')

It seems like it never enters this view because 404 is not printed. Although, if I comment out handler404 I get Django’s default “Not found” response.

I’d suggest modifying your logging to always log the output of an error to the console that way when you set DEBUG = False locally, you can still see what the exception is for the 500 error.

There’s something wrong with how you’ve configured your handler404 and it’s resulting in an unhandled exception which results in the 500 response instead of 404. Additionally, the information that print(404) does not print anything indicates that the error is occurring before your view is actually called. This points to the problem being with how the handler404 is configured.

Below is a logging setup that should emit info and above level django logs to the console. You can read more about it here.

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "simple": {
            "format": "{levelname} {message}",
            "style": "{",
        },
    },
    "handlers": {
        "console": {
            "level": "INFO",
            "filters": ["require_debug_true"],
            "class": "logging.StreamHandler",
            "formatter": "simple",
        },
    },
    "loggers": {
        "django": {
            "handlers": ["console"],
            "propagate": True,
        },
    },
}
1 Like

From the docs for the handler404 method - specifically what it must return:

If you implement a custom view, be sure it accepts request and exception arguments and returns an HttpResponseNotFound.

If you’re wanting to redirect to home on any 404-type situation, I don’t think you can do that with that handler. I believe what you’d need to do is include a path that will match any url and use that to return the redirect. (Perhaps a regex like ‘.*’)

1 Like

I implemented the “catch every other link” solution in different ways but was very buggy and I couldn’t get it to work for some of the pages. Here is what worked in the end:

I changed the custom 404’s view to this and stopped getting a 500 error. This works as intended:

def infra_404(request, exception):
    print(404)
    messages.error(request, '404: Page does not exist')
    return HttpResponseRedirect(reverse('home'))

print(404) is there for debugging only