From 94f24e2e2f6bff77fcc6ee23f5c90716becab192 Mon Sep 17 00:00:00 2001 From: Benoit C Date: Mon, 9 Jan 2012 21:09:38 +0100 Subject: [PATCH 1/3] Introduce a final methods in View class --- djangorestframework/views.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/djangorestframework/views.py b/djangorestframework/views.py index 4606e50b1..3df883916 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -154,19 +154,8 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): except ErrorResponse, exc: response = exc.response - # Always add these headers. - # - # TODO - this isn't actually the correct way to set the vary header, - # also it's currently sub-optimal for HTTP caching - need to sort that out. - response.headers['Allow'] = ', '.join(self.allowed_methods) - response.headers['Vary'] = 'Authenticate, Accept' - - # merge with headers possibly set at some point in the view - response.headers.update(self.headers) - set_script_prefix(orig_prefix) - - return self.render(response) + return self.final(request, response) def options(self, request, *args, **kwargs): response_obj = { @@ -183,6 +172,21 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): response_obj['fields'] = field_name_types return response_obj + def final(self, request, response, *args, **kargs): + """ + As initial, final can be overriden to add code that must be set after the render + """ + # Always add these headers. + # + # TODO - this isn't actually the correct way to set the vary header, + # also it's currently sub-optimal for HTTP caching - need to sort that out. + response.headers['Allow'] = ', '.join(self.allowed_methods) + response.headers['Vary'] = 'Authenticate, Accept' + + # merge with headers possibly set at some point in the view + response.headers.update(self.headers) + return self.render(response) + class ModelView(View): """ From 4ab67e789e78bb5579545d8e0df2389994a72391 Mon Sep 17 00:00:00 2001 From: Benoit C Date: Mon, 9 Jan 2012 21:09:38 +0100 Subject: [PATCH 2/3] Introduce a final methods in View class --- djangorestframework/views.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/djangorestframework/views.py b/djangorestframework/views.py index 4606e50b1..9241c9939 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -154,19 +154,8 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): except ErrorResponse, exc: response = exc.response - # Always add these headers. - # - # TODO - this isn't actually the correct way to set the vary header, - # also it's currently sub-optimal for HTTP caching - need to sort that out. - response.headers['Allow'] = ', '.join(self.allowed_methods) - response.headers['Vary'] = 'Authenticate, Accept' - - # merge with headers possibly set at some point in the view - response.headers.update(self.headers) - set_script_prefix(orig_prefix) - - return self.render(response) + return self.final(request, response, *args, **kwargs) def options(self, request, *args, **kwargs): response_obj = { @@ -183,6 +172,19 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): response_obj['fields'] = field_name_types return response_obj + def final(self, request, response, *args, **kargs): + """ + Hook for any code that needs to run after everything else in the view. + """ + # Always add these headers. + response.headers['Allow'] = ', '.join(self.allowed_methods) + # sample to allow caching using Vary http header + response.headers['Vary'] = 'Authenticate, Accept' + + # merge with headers possibly set at some point in the view + response.headers.update(self.headers) + return self.render(response) + class ModelView(View): """ From 96e91f5841c171a1bcf7571a053ab19de16f402f Mon Sep 17 00:00:00 2001 From: Benoit C Date: Tue, 10 Jan 2012 00:23:19 +0100 Subject: [PATCH 3/3] Add test for final() method --- djangorestframework/tests/views.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/djangorestframework/tests/views.py b/djangorestframework/tests/views.py index e03f6615f..ab5d75d6a 100644 --- a/djangorestframework/tests/views.py +++ b/djangorestframework/tests/views.py @@ -1,4 +1,5 @@ from django.conf.urls.defaults import patterns, url +from django.http import HttpResponse from django.test import TestCase from django.test import Client from django import forms @@ -16,6 +17,13 @@ class MockView(View): """This is a basic mock view""" pass + +class MockViewFinal(View): + """View with final() override""" + + def final(self, request, response, *args, **kwargs): + return HttpResponse('{"test": "passed"}', content_type="application/json") + class ResourceMockView(View): """This is a resource-based mock view""" @@ -43,6 +51,7 @@ urlpatterns = patterns('djangorestframework.utils.staticviews', url(r'^accounts/login$', 'api_login'), url(r'^accounts/logout$', 'api_logout'), url(r'^mock/$', MockView.as_view()), + url(r'^mock/final/$', MockViewFinal.as_view()), url(r'^resourcemock/$', ResourceMockView.as_view()), url(r'^model/$', ListOrCreateModelView.as_view(resource=MockResource)), url(r'^model/(?P[^/]+)/$', InstanceModelView.as_view(resource=MockResource)), @@ -52,6 +61,13 @@ class BaseViewTests(TestCase): """Test the base view class of djangorestframework""" urls = 'djangorestframework.tests.views' + def test_view_call_final(self): + response = self.client.options('/mock/final/') + self.assertEqual(response['Content-Type'].split(';')[0], "application/json") + parser = JSONParser(None) + (data, files) = parser.parse(StringIO(response.content)) + self.assertEqual(data['test'], 'passed') + def test_options_method_simple_view(self): response = self.client.options('/mock/') self._verify_options_response(response,