Move logic for attaching HTTP handlers into LazyViewCreator

This commit is contained in:
Jamie Matthews 2012-09-14 16:40:08 +01:00
parent 21b1116af5
commit f6488cb058

View File

@ -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')