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 4131c49a8d..bc2ac55ea1 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` @@ -143,6 +146,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`] @@ -172,6 +176,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` @@ -210,6 +215,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` @@ -248,6 +254,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` @@ -285,6 +292,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` @@ -319,6 +327,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` @@ -356,6 +365,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` @@ -396,6 +406,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` @@ -434,6 +445,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`] @@ -478,6 +490,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`] @@ -521,6 +534,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..51b0386654 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.5 + 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 9caf19365c..40c9a1b93a 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'))),