From f6488cb0589d3b11fb8d831e00d1389f3fff74b6 Mon Sep 17 00:00:00 2001 From: Jamie Matthews Date: Fri, 14 Sep 2012 16:40:08 +0100 Subject: [PATCH] Move logic for attaching HTTP handlers into LazyViewCreator --- djangorestframework/decorators.py | 51 ++++++++++++------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/djangorestframework/decorators.py b/djangorestframework/decorators.py index 22bb8d3e3..ac976bec8 100644 --- a/djangorestframework/decorators.py +++ b/djangorestframework/decorators.py @@ -16,11 +16,14 @@ class LazyViewCreator(object): This is done so that the ordering of stacked decorators is irrelevant. """ - def __init__(self): + def __init__(self, wrapped_view): + + self.wrapped_view = wrapped_view # Each item in this dictionary will be copied onto the final # class-based view that gets created when this object is called self.final_view_attrs = { + 'http_method_names': APIView.http_method_names, 'renderer_classes': APIView.renderer_classes, 'parser_classes': APIView.parser_classes, 'authentication_classes': APIView.authentication_classes, @@ -29,6 +32,9 @@ class LazyViewCreator(object): } self._cached_view = None + def handler(self, *args, **kwargs): + return self.wrapped_view(*args, **kwargs) + @property def view(self): """ @@ -44,6 +50,11 @@ class LazyViewCreator(object): for attr, value in self.final_view_attrs.items(): setattr(WrappedAPIView, attr, value) + # Attach the wrapped view function for each of the + # allowed HTTP methods + for method in WrappedAPIView.http_method_names: + setattr(WrappedAPIView, method.lower(), self.handler) + self._cached_view = WrappedAPIView.as_view() return self._cached_view @@ -55,51 +66,27 @@ class LazyViewCreator(object): return self.view(*args, **kwargs) @staticmethod - def maybe_create(func): + def maybe_create(func_or_instance): """ If the argument is already an instance of LazyViewCreator, just return it. Otherwise, create a new one. """ - if isinstance(func, LazyViewCreator): - return func - return LazyViewCreator() + if isinstance(func_or_instance, LazyViewCreator): + return func_or_instance + return LazyViewCreator(func_or_instance) -def api_view(allowed_methods): - """ - Decorator for function based views. - - @api_view(['GET', 'POST']) - def my_view(request): - # request will be an instance of `Request` - # `Response` objects will have .request set automatically - # APIException instances will be handled - """ - - def decorator(func): - wrapper = LazyViewCreator.maybe_create(func) - - @wraps(func, assigned=available_attrs(func)) - def handler(self, *args, **kwargs): - return func(*args, **kwargs) - - for method in allowed_methods: - wrapper.final_view_attrs[method.lower()] = handler - - return wrapper - return decorator - - -def _create_attribute_setting_decorator(attribute): +def _create_attribute_setting_decorator(attribute, filter=lambda item: item): def decorator(value): def inner(func): wrapper = LazyViewCreator.maybe_create(func) - wrapper.final_view_attrs[attribute] = value + wrapper.final_view_attrs[attribute] = filter(value) return wrapper return inner return decorator +api_view = _create_attribute_setting_decorator('http_method_names', filter=lambda methods: [method.lower() for method in methods]) renderer_classes = _create_attribute_setting_decorator('renderer_classes') parser_classes = _create_attribute_setting_decorator('parser_classes') authentication_classes = _create_attribute_setting_decorator('authentication_classes')