Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

""" 

The most important decorator in this module is `@api_view`, which is used 

for writing function-based views with REST framework. 

 

There are also various decorators for setting the API policies on function 

based views, as well as the `@action` and `@link` decorators, which are 

used to annotate methods on viewsets that should be included by routers. 

""" 

from __future__ import unicode_literals 

from rest_framework.compat import six 

from rest_framework.views import APIView 

import types 

 

 

def api_view(http_method_names): 

 

    """ 

    Decorator that converts a function-based view into an APIView subclass. 

    Takes a list of allowed methods for the view as an argument. 

    """ 

 

    def decorator(func): 

 

        WrappedAPIView = type( 

            six.PY3 and 'WrappedAPIView' or b'WrappedAPIView', 

            (APIView,), 

            {'__doc__': func.__doc__} 

        ) 

 

        # Note, the above allows us to set the docstring. 

        # It is the equivalent of: 

        # 

        #     class WrappedAPIView(APIView): 

        #         pass 

        #     WrappedAPIView.__doc__ = func.doc    <--- Not possible to do this 

 

        # api_view applied without (method_names) 

        assert not(isinstance(http_method_names, types.FunctionType)), \ 

            '@api_view missing list of allowed HTTP methods' 

 

        # api_view applied with eg. string instead of list of strings 

        assert isinstance(http_method_names, (list, tuple)), \ 

            '@api_view expected a list of strings, received %s' % type(http_method_names).__name__ 

 

        allowed_methods = set(http_method_names) | set(('options',)) 

        WrappedAPIView.http_method_names = [method.lower() for method in allowed_methods] 

 

        def handler(self, *args, **kwargs): 

            return func(*args, **kwargs) 

 

        for method in http_method_names: 

            setattr(WrappedAPIView, method.lower(), handler) 

 

        WrappedAPIView.__name__ = func.__name__ 

 

        WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes', 

                                                  APIView.renderer_classes) 

 

        WrappedAPIView.parser_classes = getattr(func, 'parser_classes', 

                                                APIView.parser_classes) 

 

        WrappedAPIView.authentication_classes = getattr(func, 'authentication_classes', 

                                                        APIView.authentication_classes) 

 

        WrappedAPIView.throttle_classes = getattr(func, 'throttle_classes', 

                                                  APIView.throttle_classes) 

 

        WrappedAPIView.permission_classes = getattr(func, 'permission_classes', 

                                                    APIView.permission_classes) 

 

        return WrappedAPIView.as_view() 

    return decorator 

 

 

def renderer_classes(renderer_classes): 

    def decorator(func): 

        func.renderer_classes = renderer_classes 

        return func 

    return decorator 

 

 

def parser_classes(parser_classes): 

    def decorator(func): 

        func.parser_classes = parser_classes 

        return func 

    return decorator 

 

 

def authentication_classes(authentication_classes): 

    def decorator(func): 

        func.authentication_classes = authentication_classes 

        return func 

    return decorator 

 

 

def throttle_classes(throttle_classes): 

    def decorator(func): 

        func.throttle_classes = throttle_classes 

        return func 

    return decorator 

 

 

def permission_classes(permission_classes): 

    def decorator(func): 

        func.permission_classes = permission_classes 

        return func 

    return decorator 

 

 

def link(**kwargs): 

    """ 

    Used to mark a method on a ViewSet that should be routed for GET requests. 

    """ 

    def decorator(func): 

        func.bind_to_methods = ['get'] 

        func.kwargs = kwargs 

        return func 

    return decorator 

 

 

def action(methods=['post'], **kwargs): 

    """ 

    Used to mark a method on a ViewSet that should be routed for POST requests. 

    """ 

    def decorator(func): 

        func.bind_to_methods = methods 

        func.kwargs = kwargs 

        return func 

    return decorator