diff --git a/django/views/generic/base.py b/django/views/generic/base.py index 7f60ff0773..d732af5d66 100644 --- a/django/views/generic/base.py +++ b/django/views/generic/base.py @@ -102,7 +102,9 @@ class TemplateResponseMixin(object): a list. May not be called if render_to_response is overridden. """ if self.template_name is None: - return [] + raise ImproperlyConfigured( + "TemplateResponseMixin requires either a definition of " + "'template_name' or an implementation of 'get_template_names()'") else: return [self.template_name] diff --git a/django/views/generic/detail.py b/django/views/generic/detail.py index dafdbe87b3..4fa93e1ec2 100644 --- a/django/views/generic/detail.py +++ b/django/views/generic/detail.py @@ -108,7 +108,12 @@ class SingleObjectTemplateResponseMixin(TemplateResponseMixin): Return a list of template names to be used for the request. Must return a list. May not be called if get_template is overridden. """ - names = super(SingleObjectTemplateResponseMixin, self).get_template_names() + try: + names = super(SingleObjectTemplateResponseMixin, self).get_template_names() + except ImproperlyConfigured: + # If template_name isn't specified, it's not a problem -- + # we just start with an empty list. + names = [] # If self.template_name_field is set, grab the value of the field # of that name from the object; this is the most specific template diff --git a/django/views/generic/list.py b/django/views/generic/list.py index 213b89b64d..dde23faf40 100644 --- a/django/views/generic/list.py +++ b/django/views/generic/list.py @@ -127,7 +127,12 @@ class MultipleObjectTemplateResponseMixin(TemplateResponseMixin): Return a list of template names to be used for the request. Must return a list. May not be called if get_template is overridden. """ - names = super(MultipleObjectTemplateResponseMixin, self).get_template_names() + try: + names = super(MultipleObjectTemplateResponseMixin, self).get_template_names() + except ImproperlyConfigured: + # If template_name isn't specified, it's not a problem -- + # we just start with an empty list. + names = [] # If the list is a queryset, we'll invent a template name based on the # app and model name. This name gets put at the end of the template diff --git a/tests/regressiontests/generic_views/base.py b/tests/regressiontests/generic_views/base.py index c378315b62..9f20fc4ca1 100644 --- a/tests/regressiontests/generic_views/base.py +++ b/tests/regressiontests/generic_views/base.py @@ -181,6 +181,12 @@ class TemplateViewTest(TestCase): """ self._assert_about(TemplateView.as_view(template_name='generic_views/about.html')(self.rf.get('/about/'))) + def test_template_name_required(self): + """ + A template view must provide a template name + """ + self.assertRaises(ImproperlyConfigured, self.client.get, '/template/no_template/') + def test_template_params(self): """ A generic template view passes kwargs as context. diff --git a/tests/regressiontests/generic_views/urls.py b/tests/regressiontests/generic_views/urls.py index 4c847ac78d..e5d75d585c 100644 --- a/tests/regressiontests/generic_views/urls.py +++ b/tests/regressiontests/generic_views/urls.py @@ -11,6 +11,8 @@ urlpatterns = patterns('', # views.DecoratedAboutView()), # TemplateView + (r'^template/no_template/$', + TemplateView.as_view()), (r'^template/simple/(?P\w+)/$', TemplateView.as_view(template_name='generic_views/about.html')), (r'^template/custom/(?P\w+)/$',