Commit f6488cb0 by Jamie Matthews

Move logic for attaching HTTP handlers into LazyViewCreator

parent 21b1116a
...@@ -16,11 +16,14 @@ class LazyViewCreator(object): ...@@ -16,11 +16,14 @@ class LazyViewCreator(object):
This is done so that the ordering of stacked decorators is irrelevant. 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 # Each item in this dictionary will be copied onto the final
# class-based view that gets created when this object is called # class-based view that gets created when this object is called
self.final_view_attrs = { self.final_view_attrs = {
'http_method_names': APIView.http_method_names,
'renderer_classes': APIView.renderer_classes, 'renderer_classes': APIView.renderer_classes,
'parser_classes': APIView.parser_classes, 'parser_classes': APIView.parser_classes,
'authentication_classes': APIView.authentication_classes, 'authentication_classes': APIView.authentication_classes,
...@@ -29,6 +32,9 @@ class LazyViewCreator(object): ...@@ -29,6 +32,9 @@ class LazyViewCreator(object):
} }
self._cached_view = None self._cached_view = None
def handler(self, *args, **kwargs):
return self.wrapped_view(*args, **kwargs)
@property @property
def view(self): def view(self):
""" """
...@@ -44,6 +50,11 @@ class LazyViewCreator(object): ...@@ -44,6 +50,11 @@ class LazyViewCreator(object):
for attr, value in self.final_view_attrs.items(): for attr, value in self.final_view_attrs.items():
setattr(WrappedAPIView, attr, value) 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() self._cached_view = WrappedAPIView.as_view()
return self._cached_view return self._cached_view
...@@ -55,51 +66,27 @@ class LazyViewCreator(object): ...@@ -55,51 +66,27 @@ class LazyViewCreator(object):
return self.view(*args, **kwargs) return self.view(*args, **kwargs)
@staticmethod @staticmethod
def maybe_create(func): def maybe_create(func_or_instance):
""" """
If the argument is already an instance of LazyViewCreator, If the argument is already an instance of LazyViewCreator,
just return it. Otherwise, create a new one. just return it. Otherwise, create a new one.
""" """
if isinstance(func, LazyViewCreator): if isinstance(func_or_instance, LazyViewCreator):
return func return func_or_instance
return LazyViewCreator() 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 decorator(value):
def inner(func): def inner(func):
wrapper = LazyViewCreator.maybe_create(func) wrapper = LazyViewCreator.maybe_create(func)
wrapper.final_view_attrs[attribute] = value wrapper.final_view_attrs[attribute] = filter(value)
return wrapper return wrapper
return inner return inner
return decorator 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') renderer_classes = _create_attribute_setting_decorator('renderer_classes')
parser_classes = _create_attribute_setting_decorator('parser_classes') parser_classes = _create_attribute_setting_decorator('parser_classes')
authentication_classes = _create_attribute_setting_decorator('authentication_classes') authentication_classes = _create_attribute_setting_decorator('authentication_classes')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment