Fixed #30318 -- Added check for importability of arguments of custom error handler views.
Thanks to Jon on Stack Overflow for reporting the issue.
This commit is contained in:
parent
fc9566d42d
commit
a5accc0368
|
@ -15,7 +15,7 @@ from urllib.parse import quote
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.checks import Error, Warning
|
from django.core.checks import Error, Warning
|
||||||
from django.core.checks.urls import check_resolver
|
from django.core.checks.urls import check_resolver
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.http import RFC3986_SUBDELIMS, escape_leading_slashes
|
from django.utils.http import RFC3986_SUBDELIMS, escape_leading_slashes
|
||||||
|
@ -405,7 +405,15 @@ class URLResolver:
|
||||||
# All handlers take (request, exception) arguments except handler500
|
# All handlers take (request, exception) arguments except handler500
|
||||||
# which takes (request).
|
# which takes (request).
|
||||||
for status_code, num_parameters in [(400, 2), (403, 2), (404, 2), (500, 1)]:
|
for status_code, num_parameters in [(400, 2), (403, 2), (404, 2), (500, 1)]:
|
||||||
handler, param_dict = self.resolve_error_handler(status_code)
|
try:
|
||||||
|
handler, param_dict = self.resolve_error_handler(status_code)
|
||||||
|
except (ImportError, ViewDoesNotExist) as e:
|
||||||
|
path = getattr(self.urlconf_module, 'handler%s' % status_code)
|
||||||
|
msg = (
|
||||||
|
"The custom handler{status_code} view '{path}' could not be imported."
|
||||||
|
).format(status_code=status_code, path=path)
|
||||||
|
messages.append(Error(msg, hint=str(e), id='urls.E008'))
|
||||||
|
continue
|
||||||
signature = inspect.signature(handler)
|
signature = inspect.signature(handler)
|
||||||
args = [None] * num_parameters
|
args = [None] * num_parameters
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -473,6 +473,8 @@ The following checks are performed on your URL configuration:
|
||||||
end with a slash.
|
end with a slash.
|
||||||
* **urls.E007**: The custom ``handlerXXX`` view ``'path.to.view'`` does not
|
* **urls.E007**: The custom ``handlerXXX`` view ``'path.to.view'`` does not
|
||||||
take the correct number of arguments (…).
|
take the correct number of arguments (…).
|
||||||
|
* **urls.E008**: The custom ``handlerXXX`` view ``'path.to.view'`` could not be
|
||||||
|
imported.
|
||||||
|
|
||||||
``contrib`` app checks
|
``contrib`` app checks
|
||||||
======================
|
======================
|
||||||
|
|
|
@ -46,3 +46,6 @@ Bugfixes
|
||||||
* Fixed a regression in Django 2.2 where
|
* Fixed a regression in Django 2.2 where
|
||||||
:class:`~django.contrib.postgres.search.SearchVector` generates SQL that is
|
:class:`~django.contrib.postgres.search.SearchVector` generates SQL that is
|
||||||
not indexable (:ticket:`30385`).
|
not indexable (:ticket:`30385`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 2.2 that caused an exception to be raised when
|
||||||
|
a custom error handler could not be imported (:ticket:`30318`).
|
||||||
|
|
|
@ -181,6 +181,29 @@ class CheckCustomErrorHandlersTests(SimpleTestCase):
|
||||||
id='urls.E007',
|
id='urls.E007',
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@override_settings(ROOT_URLCONF='check_framework.urls.bad_error_handlers_invalid_path')
|
||||||
|
def test_bad_handlers_invalid_path(self):
|
||||||
|
result = check_url_config(None)
|
||||||
|
paths = [
|
||||||
|
'django.views.bad_handler',
|
||||||
|
'django.invalid_module.bad_handler',
|
||||||
|
'invalid_module.bad_handler',
|
||||||
|
'django',
|
||||||
|
]
|
||||||
|
hints = [
|
||||||
|
"Could not import '{}'. View does not exist in module django.views.",
|
||||||
|
"Could not import '{}'. Parent module django.invalid_module does not exist.",
|
||||||
|
"No module named 'invalid_module'",
|
||||||
|
"Could not import '{}'. The path must be fully qualified.",
|
||||||
|
]
|
||||||
|
for code, path, hint, error in zip([400, 403, 404, 500], paths, hints, result):
|
||||||
|
with self.subTest('handler{}'.format(code)):
|
||||||
|
self.assertEqual(error, Error(
|
||||||
|
"The custom handler{} view '{}' could not be imported.".format(code, path),
|
||||||
|
hint=hint.format(path),
|
||||||
|
id='urls.E008',
|
||||||
|
))
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF='check_framework.urls.good_error_handlers')
|
@override_settings(ROOT_URLCONF='check_framework.urls.good_error_handlers')
|
||||||
def test_good_handlers(self):
|
def test_good_handlers(self):
|
||||||
result = check_url_config(None)
|
result = check_url_config(None)
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
urlpatterns = []
|
||||||
|
|
||||||
|
handler400 = 'django.views.bad_handler'
|
||||||
|
handler403 = 'django.invalid_module.bad_handler'
|
||||||
|
handler404 = 'invalid_module.bad_handler'
|
||||||
|
handler500 = 'django'
|
Loading…
Reference in New Issue