diff --git a/django/views/generic/detail.py b/django/views/generic/detail.py index 5ce8092c67..466954c03a 100644 --- a/django/views/generic/detail.py +++ b/django/views/generic/detail.py @@ -137,28 +137,34 @@ class SingleObjectTemplateResponseMixin(TemplateResponseMixin): # 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 - # name, if given. - if self.object and self.template_name_field: - name = getattr(self.object, self.template_name_field, None) - if name: - names.insert(0, name) + # 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 + # name, if given. + if self.object and self.template_name_field: + name = getattr(self.object, self.template_name_field, None) + if name: + names.insert(0, name) + + # The least-specific option is the default /_detail.html; + # only use this if the object in question is a model. + if isinstance(self.object, models.Model): + names.append("%s/%s%s.html" % ( + self.object._meta.app_label, + self.object._meta.model_name, + self.template_name_suffix + )) + elif hasattr(self, 'model') and self.model is not None and issubclass(self.model, models.Model): + names.append("%s/%s%s.html" % ( + self.model._meta.app_label, + self.model._meta.model_name, + self.template_name_suffix + )) + + # If we still haven't managed to find any template names, we should + # re-raise the ImproperlyConfigured to alert the user. + if not names: + raise - # The least-specific option is the default /_detail.html; - # only use this if the object in question is a model. - if isinstance(self.object, models.Model): - names.append("%s/%s%s.html" % ( - self.object._meta.app_label, - self.object._meta.model_name, - self.template_name_suffix - )) - elif hasattr(self, 'model') and self.model is not None and issubclass(self.model, models.Model): - names.append("%s/%s%s.html" % ( - self.model._meta.app_label, - self.model._meta.model_name, - self.template_name_suffix - )) return names diff --git a/tests/generic_views/test_base.py b/tests/generic_views/test_base.py index b1dd7a3040..5dd6815d05 100644 --- a/tests/generic_views/test_base.py +++ b/tests/generic_views/test_base.py @@ -468,3 +468,15 @@ class UseMultipleObjectMixinTest(unittest.TestCase): # Overwrite the view's queryset with queryset from kwarg context = test_view.get_context_data(object_list=queryset) self.assertEqual(context['object_list'], queryset) + + +class SingleObjectTemplateResponseMixinTest(unittest.TestCase): + + def test_template_mixin_without_template(self): + """ + We want to makes sure that if you use a template mixin, but forget the + template, it still tells you it's ImproperlyConfigured instead of + TemplateDoesNotExist. + """ + view = views.TemplateResponseWithoutTemplate() + self.assertRaises(ImproperlyConfigured, view.get_template_names) diff --git a/tests/generic_views/views.py b/tests/generic_views/views.py index f839b53753..aaff644a14 100644 --- a/tests/generic_views/views.py +++ b/tests/generic_views/views.py @@ -92,6 +92,14 @@ class NaiveAuthorCreate(generic.CreateView): fields = '__all__' +class TemplateResponseWithoutTemplate(generic.detail.SingleObjectTemplateResponseMixin, generic.View): + # we don't define the usual template_name here + + def __init__(self): + # Dummy object, but attr is required by get_template_name() + self.object = None + + class AuthorCreate(generic.CreateView): model = Author success_url = '/list/authors/'