diff --git a/django/views/generic/base.py b/django/views/generic/base.py index 9c82a29d8a..d50d6bbc55 100644 --- a/django/views/generic/base.py +++ b/django/views/generic/base.py @@ -113,6 +113,7 @@ class TemplateResponseMixin(object): """ template_name = None response_class = TemplateResponse + content_type = None def render_to_response(self, context, **response_kwargs): """ @@ -122,6 +123,7 @@ class TemplateResponseMixin(object): If any keyword arguments are provided, they will be passed to the constructor of the response class. """ + response_kwargs.setdefault('content_type', self.content_type) return self.response_class( request = self.request, template = self.get_template_names(), diff --git a/docs/ref/class-based-views/flattened-index.txt b/docs/ref/class-based-views/flattened-index.txt index 2e75363c58..b98a35634e 100644 --- a/docs/ref/class-based-views/flattened-index.txt +++ b/docs/ref/class-based-views/flattened-index.txt @@ -32,6 +32,7 @@ TemplateView **Attributes** (with optional accessor): +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.base.TemplateResponseMixin.response_class` * :attr:`~django.views.generic.base.TemplateResponseMixin.template_name` [:meth:`~django.views.generic.base.TemplateResponseMixin.get_template_names`] @@ -79,6 +80,7 @@ DetailView **Attributes** (with optional accessor): +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.detail.SingleObjectMixin.context_object_name` [:meth:`~django.views.generic.detail.SingleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.detail.SingleObjectMixin.model` @@ -112,6 +114,7 @@ ListView **Attributes** (with optional accessor): * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.list.MultipleObjectMixin.model` @@ -144,6 +147,7 @@ FormView **Attributes** (with optional accessor): +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.edit.FormMixin.form_class` [:meth:`~django.views.generic.edit.FormMixin.get_form_class`] * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.edit.FormMixin.initial` [:meth:`~django.views.generic.edit.FormMixin.get_initial`] @@ -173,6 +177,7 @@ CreateView **Attributes** (with optional accessor): +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.detail.SingleObjectMixin.context_object_name` [:meth:`~django.views.generic.detail.SingleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.edit.FormMixin.form_class` [:meth:`~django.views.generic.edit.FormMixin.get_form_class`] * :attr:`~django.views.generic.base.View.http_method_names` @@ -211,6 +216,7 @@ UpdateView **Attributes** (with optional accessor): +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.detail.SingleObjectMixin.context_object_name` [:meth:`~django.views.generic.detail.SingleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.edit.FormMixin.form_class` [:meth:`~django.views.generic.edit.FormMixin.get_form_class`] * :attr:`~django.views.generic.base.View.http_method_names` @@ -249,6 +255,7 @@ DeleteView **Attributes** (with optional accessor): +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.detail.SingleObjectMixin.context_object_name` [:meth:`~django.views.generic.detail.SingleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.base.View.http_method_names` * :attr:`~django.views.generic.detail.SingleObjectMixin.model` @@ -286,6 +293,7 @@ ArchiveIndexView * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.base.View.http_method_names` @@ -321,6 +329,7 @@ YearArchiveView * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.base.View.http_method_names` @@ -359,6 +368,7 @@ MonthArchiveView * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.base.View.http_method_names` @@ -400,6 +410,7 @@ WeekArchiveView * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.base.View.http_method_names` @@ -439,6 +450,7 @@ DayArchiveView * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.dates.DayMixin.day` [:meth:`~django.views.generic.dates.DayMixin.get_day`] @@ -484,6 +496,7 @@ TodayArchiveView * :attr:`~django.views.generic.list.MultipleObjectMixin.allow_empty` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_allow_empty`] * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.list.MultipleObjectMixin.context_object_name` [:meth:`~django.views.generic.list.MultipleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.dates.DayMixin.day` [:meth:`~django.views.generic.dates.DayMixin.get_day`] @@ -528,6 +541,7 @@ DateDetailView **Attributes** (with optional accessor): * :attr:`~django.views.generic.dates.DateMixin.allow_future` [:meth:`~django.views.generic.dates.DateMixin.get_allow_future`] +* :attr:`~django.views.generic.base.TemplateResponseMixin.content_type` * :attr:`~django.views.generic.detail.SingleObjectMixin.context_object_name` [:meth:`~django.views.generic.detail.SingleObjectMixin.get_context_object_name`] * :attr:`~django.views.generic.dates.DateMixin.date_field` [:meth:`~django.views.generic.dates.DateMixin.get_date_field`] * :attr:`~django.views.generic.dates.DayMixin.day` [:meth:`~django.views.generic.dates.DayMixin.get_day`] diff --git a/docs/ref/class-based-views/mixins-simple.txt b/docs/ref/class-based-views/mixins-simple.txt index e2e6084e8e..f1ec0482d0 100644 --- a/docs/ref/class-based-views/mixins-simple.txt +++ b/docs/ref/class-based-views/mixins-simple.txt @@ -64,6 +64,15 @@ TemplateResponseMixin instantiation, create a ``TemplateResponse`` subclass and assign it to ``response_class``. + .. attribute:: content_type + + .. versionadded:: 1.6 + The ``content_type`` attribute was added. + + The content type to use for the response. ``content_type`` is passed + as a keyword argument to ``response_class``. Default is ``None`` -- + meaning that Django uses :setting:`DEFAULT_CONTENT_TYPE`. + **Methods** .. method:: render_to_response(context, **response_kwargs) diff --git a/tests/regressiontests/generic_views/base.py b/tests/regressiontests/generic_views/base.py index c7ad7a0deb..fd2abb0aa7 100644 --- a/tests/regressiontests/generic_views/base.py +++ b/tests/regressiontests/generic_views/base.py @@ -312,6 +312,11 @@ class TemplateViewTest(TestCase): self.assertNotEqual(response.content, response2.content) + def test_content_type(self): + response = self.client.get('/template/content_type/') + self.assertEqual(response['Content-Type'], 'text/plain') + + class RedirectViewTest(unittest.TestCase): rf = RequestFactory() diff --git a/tests/regressiontests/generic_views/urls.py b/tests/regressiontests/generic_views/urls.py index 34b37fa7c4..57309053d3 100644 --- a/tests/regressiontests/generic_views/urls.py +++ b/tests/regressiontests/generic_views/urls.py @@ -20,6 +20,8 @@ urlpatterns = patterns('', TemplateView.as_view(template_name='generic_views/about.html')), (r'^template/custom/(?P\w+)/$', views.CustomTemplateView.as_view(template_name='generic_views/about.html')), + (r'^template/content_type/$', + TemplateView.as_view(template_name='generic_views/robots.txt', content_type='text/plain')), (r'^template/cached/(?P\w+)/$', cache_page(2.0)(TemplateView.as_view(template_name='generic_views/about.html'))),