Coverage for audoma/drf/generics.py: 73%

1 from typing import Type

2

3 from rest_framework import generics

4 from rest_framework.serializers import BaseSerializer

5

6

7 class GenericAPIView(generics.GenericAPIView):

8

9 """

10 Extended GenericAPIView known from rest_framework.

11 This class extends `get_serializer` and `get_serializer_class` methods.

12 Also provides `get_result_serializer`, which is a shourtcut for `get_serializer` with proper param.

13 """

14

15 def get_serializer(self, *args, **kwargs) -> BaseSerializer:

16 """

17 Passes additional param to `get_serializer_class`.

18

19 kwargs:

20 serializer_type - defines if serializer is collect or result serializer.

21 result serializer will be used to produce response, collect to process incoming data.

22 serializer_class - it is possible to pass serializer_class to get_serializer, this will

23 ends with returning passed serializer_class object.

24

25 Returns:

26 Object of obtained serializer class.

27 """

28 many = kwargs.get("many", False)

29

30 serializer_type = kwargs.pop("serializer_type", "collect")

31 serializer_class = kwargs.pop(

32 "serializer_class",

33 self.get_serializer_class(type=serializer_type, many=many),

34 )

35 kwargs["context"] = self.get_serializer_context()

36

37 return serializer_class(*args, **kwargs)

38

39 # needed by AudomaSwaggerAutoSchema

40 def get_result_serializer(self, *args, **kwargs) -> BaseSerializer:

41 """

42 Shortuct for get_serializer.

43 Simply has serializer_type set to `result`

44 """

45 return self.get_serializer(*args, serializer_type="result", **kwargs)

46

47 def get_serializer_class(

48 self, type: str = "collect", many: bool = False

49 ) -> Type[BaseSerializer]:

50 """

51 Extends defuault `get_serializer_class` method.

52 This returns proper serializer_class for current request.

53

54 Args:

55 type - type of serializer to be returned, it may be collect or result serializer.

56

57 Returns:

58 This returns serializer_class

59

60 """

61 assert self.action not in [

62 "post",

63 "put",

64 "delete",

65 "patch",

66 "options",

67 "get",

68 "head",

69 ]

70 method = self.request.method.lower()

71 if self.action == "metadata":

72 action = self.action_map.get("post", "list")

73 else:

74 action = self.action

75 attr_names = [

76 "%s_%s_%s_serializer_class" % (method, action, type),

77 "%s_%s_serializer_class" % (action, type),

78 "%s_%s_serializer_class" % (method, action),

79 "%s_serializer_class" % (action),

80 "common_%s_serializer_class" % (type),

81 "serializer_class",

82 ]

83 for attr_name in attr_names:

84 try:

85 serializer_class = getattr(self, attr_name)

86 except AttributeError:

87 continue

88 else:

89 break

90

91 assert serializer_class is not None, (

92 "'%s' should either include a `serializer_class` attribute, "

93 "or override the `get_serializer_class()` method." % self.__class__.__name__

94 )

95

96 if (

97 type == "result"

98 and self.action != "list"

99 and hasattr(serializer_class, "get_result_serializer_class")

100 ):

101 assert callable(serializer_class.get_result_serializer_class)

102 serializer_class = serializer_class.get_result_serializer_class(many=many)

103

104 return serializer_class