Source code for cms_qe.views.errors
import logging
from typing import Callable
from cms.views import details
from django.conf import settings
from django.http import Http404, HttpRequest, HttpResponse
from django.http.response import HttpResponseBase
from django.shortcuts import render
from django.utils.translation import gettext as _
from django.views.decorators.csrf import requires_csrf_token
from ..constants import QE_STATUS_CODE
__all__ = ('handler403', 'handler404', 'handler500', 'handler503', 'get_error_handler')
[docs]def get_error_handler(code: int) -> Callable[[HttpRequest], HttpResponseBase]:
"""
Decorator creating error handler for specific HTTP status code.
When CMS page with slug ``errorCODE`` exists, then is shown that
page, otherwise generic one. Page is not cached because of that.
Possible slugs:
* error403 (forbidden)
* error404 (not found)
* error503 (service unavailable)
"""
# pylint: disable=missing-docstring,unused-argument
# https://docs.djangoproject.com/en/1.11/ref/csrf/#csrfviewmiddleware-process-view-not-used
@requires_csrf_token
def error_handler(request: HttpRequest, *args, **kwds) -> HttpResponseBase:
slug = f'error{code}'
if hasattr(request, '_current_page_cache'):
delattr(request, '_current_page_cache')
try:
response = details(request, slug)
except Http404:
response = render(request, 'cms_qe/error.html', context={'slug': slug})
# Save page status code into the page headers for later restore in middleware when page is cached.
response[QE_STATUS_CODE] = code
# In debug any response with status_code 404 is transformed to Django error
# page and is not possible to check that page. We want to be able to check
# not found page in debug as well.
if response and not settings.DEBUG:
response.status_code = code
return response
return error_handler
# pylint: disable=invalid-name
handler403 = get_error_handler(403)
handler404 = get_error_handler(404)
handler503 = get_error_handler(503)
[docs]@requires_csrf_token
def handler500(request: HttpRequest) -> HttpResponseBase:
"""
When application fail on internal error, Django CMS has problem
to render any page. They don't have any API for rendering any page
so it's impossible to get it right. Solution could be just redirect
to page with given slug but it could also hang in infinite loop of
redirection if there would be problem on page with slug error500.
That's why we simply just use different template which cannot be
changed in admin by user. To override default template, just create
your own ``cms_qe/internal_error.html`` or change ``handler500``
to your own view.
"""
try:
return render(request, 'cms_qe/internal_error.html', status=500)
except Exception: # pylint: disable=broad-except
logging.exception('Exception while rendering page 500')
title, message = _('Internal error'), _('Something went very wrong. Please try again later.')
return HttpResponse(f'<h1>{title}</h1><p>{message}</p>', status=500)