| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 | from functools import update_wrapper
from django.utils.decorators import classonlymethod
from rest_framework import views, generics, mixins
class ViewSetMixin(object):
    """
    This is the magic.
    Overrides `.as_view()` so that it takes an `actions` keyword that performs
    the binding of HTTP methods to actions on the Resource.
    For example, to create a concrete view binding the 'GET' and 'POST' methods
    to the 'list' and 'create' actions...
    view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
    """
    _is_viewset = True
    @classonlymethod
    def as_view(cls, actions=None, name_suffix=None, **initkwargs):
        """
        Main entry point for a request-response process.
        Because of the way class based views create a closure around the
        instantiated view, we need to totally reimplement `.as_view`,
        and slightly modify the view function that is created and returned.
        """
        # sanitize keyword arguments
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r" % (
                    cls.__name__, key))
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            # Bind methods to actions
            # This is the bit that's different to a standard view
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)
            # Patch this in as it's otherwise only present from 1.5 onwards
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            # And continue as usual
            return self.dispatch(request, *args, **kwargs)
        # take name and docstring from class
        update_wrapper(view, cls, updated=())
        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        view.cls = cls
        return view
class ViewSet(ViewSetMixin, views.APIView):
    pass
# Note the inheritence of both MultipleObjectAPIView *and* SingleObjectAPIView
# is a bit weird given the diamond inheritence, but it will work for now.
# There's some implementation clean up that can happen later.
class ModelViewSet(mixins.CreateModelMixin,
                    mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    mixins.ListModelMixin,
                    ViewSetMixin,
                    generics.GenericAPIView):
    pass
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           ViewSetMixin,
                           generics.GenericAPIView):
    pass
 |