diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 0de7525b8..5fc6c6865 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -10,46 +10,17 @@ except ImportError: import StringIO -# django.views.generic.View (Django >= 1.3) -try: +# First implementation of Django class-based views did not include head method +# in base View class - https://code.djangoproject.com/ticket/15668 +if django.VERSION >= (1, 4): from django.views.generic import View - if not hasattr(View, 'head'): - # First implementation of Django class-based views did not include head method - # in base View class - https://code.djangoproject.com/ticket/15668 - class ViewPlusHead(View): - def head(self, request, *args, **kwargs): - return self.get(request, *args, **kwargs) - View = ViewPlusHead - -except ImportError: - from django import http +else: + from django.views.generic import View as _View + from django.utils.decorators import classonlymethod from django.utils.functional import update_wrapper - # from django.utils.log import getLogger - # from django.utils.decorators import classonlymethod - # logger = getLogger('django.request') - We'll just drop support for logger if running Django <= 1.2 - # Might be nice to fix this up sometime to allow rest_framework.compat.View to match 1.3's View more closely - - class View(object): - """ - Intentionally simple parent class for all views. Only implements - dispatch-by-method and simple sanity checking. - """ - - http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace'] - - def __init__(self, **kwargs): - """ - Constructor. Called in the URLconf; can contain helpful extra - keyword arguments, and other things. - """ - # Go through keyword arguments, and either save their values to our - # instance, or raise an error. - for key, value in kwargs.iteritems(): - setattr(self, key, value) - - # @classonlymethod - We'll just us classmethod instead if running Django <= 1.2 - @classmethod + class View(_View): + @classonlymethod def as_view(cls, **initkwargs): """ Main entry point for a request-response process. @@ -66,6 +37,8 @@ except ImportError: def view(request, *args, **kwargs): self = cls(**initkwargs) + if hasattr(self, 'get') and not hasattr(self, 'head'): + self.head = self.get return self.dispatch(request, *args, **kwargs) # take name and docstring from class @@ -76,32 +49,6 @@ except ImportError: update_wrapper(view, cls.dispatch, assigned=()) return view - def dispatch(self, request, *args, **kwargs): - # Try to dispatch to the right method; if a method doesn't exist, - # defer to the error handler. Also defer to the error handler if the - # request method isn't on the approved list. - if request.method.lower() in self.http_method_names: - handler = getattr(self, request.method.lower(), self.http_method_not_allowed) - else: - handler = self.http_method_not_allowed - self.request = request - self.args = args - self.kwargs = kwargs - return handler(request, *args, **kwargs) - - def http_method_not_allowed(self, request, *args, **kwargs): - allowed_methods = [m for m in self.http_method_names if hasattr(self, m)] - #logger.warning('Method Not Allowed (%s): %s' % (request.method, request.path), - # extra={ - # 'status_code': 405, - # 'request': self.request - # } - #) - return http.HttpResponseNotAllowed(allowed_methods) - - def head(self, request, *args, **kwargs): - return self.get(request, *args, **kwargs) - # PUT, DELETE do not require CSRF until 1.4. They should. Make it better. if django.VERSION >= (1, 4): from django.middleware.csrf import CsrfViewMiddleware