mirror of https://github.com/django/django.git
Fixed #32105 -- Added template paths as ExceptionReporter class attributes.
This allows replacement of the debugging templates without having to copy-paste the `get_traceback_html` and `get_traceback_text` functions into a subclass. Thanks to Nick Pope for review.
This commit is contained in:
parent
411cc0ae18
commit
68e33b347d
|
@ -245,6 +245,9 @@ class SafeExceptionReporterFilter:
|
|||
|
||||
class ExceptionReporter:
|
||||
"""Organize and coordinate reporting on exceptions."""
|
||||
html_template_path = CURRENT_DIR / 'templates' / 'technical_500.html'
|
||||
text_template_path = CURRENT_DIR / 'templates' / 'technical_500.txt'
|
||||
|
||||
def __init__(self, request, exc_type, exc_value, tb, is_email=False):
|
||||
self.request = request
|
||||
self.filter = get_exception_reporter_filter(self.request)
|
||||
|
@ -331,14 +334,14 @@ class ExceptionReporter:
|
|||
|
||||
def get_traceback_html(self):
|
||||
"""Return HTML version of debug 500 HTTP error page."""
|
||||
with Path(CURRENT_DIR, 'templates', 'technical_500.html').open(encoding='utf-8') as fh:
|
||||
with self.html_template_path.open(encoding='utf-8') as fh:
|
||||
t = DEBUG_ENGINE.from_string(fh.read())
|
||||
c = Context(self.get_traceback_data(), use_l10n=False)
|
||||
return t.render(c)
|
||||
|
||||
def get_traceback_text(self):
|
||||
"""Return plain text version of debug 500 HTTP error page."""
|
||||
with Path(CURRENT_DIR, 'templates', 'technical_500.txt').open(encoding='utf-8') as fh:
|
||||
with self.text_template_path.open(encoding='utf-8') as fh:
|
||||
t = DEBUG_ENGINE.from_string(fh.read())
|
||||
c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
|
||||
return t.render(c)
|
||||
|
|
|
@ -325,6 +325,22 @@ Your custom reporter class needs to inherit from
|
|||
|
||||
.. class:: ExceptionReporter
|
||||
|
||||
.. attribute:: html_template_path
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
A :class:`pathlib.Path` representing the absolute filesystem path to a
|
||||
template for rendering the HTML representation of the exception.
|
||||
Defaults to the Django provided template.
|
||||
|
||||
.. attribute:: text_template_path
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
A :class:`pathlib.Path` representing the absolute filesystem path to a
|
||||
template for rendering the plain-text representation of the exception.
|
||||
Defaults to the Django provided template.
|
||||
|
||||
.. method:: get_traceback_data()
|
||||
|
||||
Return a dictionary containing traceback information.
|
||||
|
|
|
@ -188,7 +188,10 @@ Email
|
|||
Error Reporting
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
* ...
|
||||
* Custom :class:`~django.views.debug.ExceptionReporter` subclasses can now set
|
||||
the :attr:`~django.views.debug.ExceptionReporter.html_template_path` and
|
||||
:attr:`~django.views.debug.ExceptionReporter.text_template_path` class
|
||||
attributes to override the templates used to render exception reports.
|
||||
|
||||
File Storage
|
||||
~~~~~~~~~~~~
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<h1>Oh no, an error occurred!</h1>
|
|
@ -0,0 +1 @@
|
|||
Oh dear, an error occurred!
|
|
@ -293,6 +293,21 @@ class DebugViewTests(SimpleTestCase):
|
|||
response = self.client.get('/raises500/')
|
||||
self.assertContains(response, 'custom traceback text', status_code=500)
|
||||
|
||||
@override_settings(DEFAULT_EXCEPTION_REPORTER='view_tests.views.TemplateOverrideExceptionReporter')
|
||||
def test_template_override_exception_reporter(self):
|
||||
with self.assertLogs('django.request', 'ERROR'):
|
||||
response = self.client.get('/raises500/')
|
||||
self.assertContains(
|
||||
response,
|
||||
'<h1>Oh no, an error occurred!</h1>',
|
||||
status_code=500,
|
||||
html=True,
|
||||
)
|
||||
|
||||
with self.assertLogs('django.request', 'ERROR'):
|
||||
response = self.client.get('/raises500/', HTTP_ACCEPT='text/plain')
|
||||
self.assertContains(response, 'Oh dear, an error occurred!', status_code=500)
|
||||
|
||||
|
||||
class DebugViewQueriesAllowedTests(SimpleTestCase):
|
||||
# May need a query to initialize MySQL connection
|
||||
|
|
|
@ -2,6 +2,7 @@ import datetime
|
|||
import decimal
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.exceptions import (
|
||||
BadRequest, PermissionDenied, SuspiciousOperation,
|
||||
|
@ -18,6 +19,8 @@ from django.views.decorators.debug import (
|
|||
sensitive_post_parameters, sensitive_variables,
|
||||
)
|
||||
|
||||
TEMPLATES_PATH = Path(__file__).resolve().parent / 'templates'
|
||||
|
||||
|
||||
def index_page(request):
|
||||
"""Dummy index page"""
|
||||
|
@ -240,6 +243,11 @@ class CustomExceptionReporter(ExceptionReporter):
|
|||
return self.custom_traceback_text
|
||||
|
||||
|
||||
class TemplateOverrideExceptionReporter(ExceptionReporter):
|
||||
html_template_path = TEMPLATES_PATH / 'my_technical_500.html'
|
||||
text_template_path = TEMPLATES_PATH / 'my_technical_500.txt'
|
||||
|
||||
|
||||
def custom_reporter_class_view(request):
|
||||
request.exception_reporter_class = CustomExceptionReporter
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue