From 1c5fe467bd838c8521ca7c7427d8196f08a24f80 Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Sun, 13 Dec 2009 20:29:04 +0000 Subject: [PATCH] Fixed #10326: handler500 and handler404 may now be callables. Thanks, dcwatson, adurdin. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11854 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/urlresolvers.py | 3 +-- docs/topics/http/urls.txt | 16 +++++++++---- .../urlpatterns_reverse/tests.py | 23 ++++++++++++++++++- .../urls_error_handlers.py | 8 +++++++ .../urls_error_handlers_callables.py | 9 ++++++++ 5 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 tests/regressiontests/urlpatterns_reverse/urls_error_handlers.py create mode 100644 tests/regressiontests/urlpatterns_reverse/urls_error_handlers_callables.py diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index a924afeaf8..c721015d62 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -257,9 +257,8 @@ class RegexURLResolver(object): def _resolve_special(self, view_type): callback = getattr(self.urlconf_module, 'handler%s' % view_type) - mod_name, func_name = get_mod_func(callback) try: - return getattr(import_module(mod_name), func_name), {} + return get_callable(callback), {} except (ImportError, AttributeError), e: raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e)) diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt index fd45e79876..0a5d04cdae 100644 --- a/docs/topics/http/urls.txt +++ b/docs/topics/http/urls.txt @@ -253,24 +253,30 @@ handler404 .. data:: handler404 -A string representing the full Python import path to the view that should be -called if none of the URL patterns match. +A callable, or a string representing the full Python import path to the view +that should be called if none of the URL patterns match. By default, this is ``'django.views.defaults.page_not_found'``. That default value should suffice. +.. versionchanged:: 1.2 + Previous versions of Django only accepted strings representing import paths. + handler500 ---------- .. data:: handler500 -A string representing the full Python import path to the view that should be -called in case of server errors. Server errors happen when you have runtime -errors in view code. +A callable, or a string representing the full Python import path to the view +that should be called in case of server errors. Server errors happen when you +have runtime errors in view code. By default, this is ``'django.views.defaults.server_error'``. That default value should suffice. +.. versionchanged:: 1.2 + Previous versions of Django only accepted strings representing import paths. + include ------- diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py index 34c9db25d3..1dc85b0424 100644 --- a/tests/regressiontests/urlpatterns_reverse/tests.py +++ b/tests/regressiontests/urlpatterns_reverse/tests.py @@ -244,7 +244,6 @@ class NamespaceTests(TestCase): self.assertEquals('/other1/inner/37/42/', reverse('nodefault:urlobject-view', args=[37,42], current_app='other-ns1')) self.assertEquals('/other1/inner/42/37/', reverse('nodefault:urlobject-view', kwargs={'arg1':42, 'arg2':37}, current_app='other-ns1')) - class RequestURLconfTests(TestCase): def setUp(self): self.root_urlconf = settings.ROOT_URLCONF @@ -276,3 +275,25 @@ class RequestURLconfTests(TestCase): response = self.client.get('/second_test/') self.assertEqual(response.status_code, 200) self.assertEqual(response.content, 'outer:,inner:/second_test/') + +class ErrorHandlerResolutionTests(TestCase): + """Tests for handler404 and handler500""" + + def setUp(self): + from django.core.urlresolvers import RegexURLResolver + urlconf = 'regressiontests.urlpatterns_reverse.urls_error_handlers' + urlconf_callables = 'regressiontests.urlpatterns_reverse.urls_error_handlers_callables' + self.resolver = RegexURLResolver(r'^$', urlconf) + self.callable_resolver = RegexURLResolver(r'^$', urlconf_callables) + + def test_named_handlers(self): + from views import empty_view + handler = (empty_view, {}) + self.assertEqual(self.resolver.resolve404(), handler) + self.assertEqual(self.resolver.resolve500(), handler) + + def test_callable_handers(self): + from views import empty_view + handler = (empty_view, {}) + self.assertEqual(self.callable_resolver.resolve404(), handler) + self.assertEqual(self.callable_resolver.resolve500(), handler) diff --git a/tests/regressiontests/urlpatterns_reverse/urls_error_handlers.py b/tests/regressiontests/urlpatterns_reverse/urls_error_handlers.py new file mode 100644 index 0000000000..c2e0d32498 --- /dev/null +++ b/tests/regressiontests/urlpatterns_reverse/urls_error_handlers.py @@ -0,0 +1,8 @@ +# Used by the ErrorHandlerResolutionTests test case. + +from django.conf.urls.defaults import patterns + +urlpatterns = patterns('') + +handler404 = 'regressiontests.urlpatterns_reverse.views.empty_view' +handler500 = 'regressiontests.urlpatterns_reverse.views.empty_view' diff --git a/tests/regressiontests/urlpatterns_reverse/urls_error_handlers_callables.py b/tests/regressiontests/urlpatterns_reverse/urls_error_handlers_callables.py new file mode 100644 index 0000000000..00f25a7236 --- /dev/null +++ b/tests/regressiontests/urlpatterns_reverse/urls_error_handlers_callables.py @@ -0,0 +1,9 @@ +# Used by the ErrorHandlerResolutionTests test case. + +from django.conf.urls.defaults import patterns +from views import empty_view + +urlpatterns = patterns('') + +handler404 = empty_view +handler500 = empty_view