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

30 statements  

« prev     ^ index     » next       coverage.py v6.4.2, created at 2022-08-08 06:12 +0000

1from typing import Type 

2 

3from rest_framework import generics 

4from rest_framework.serializers import BaseSerializer 

5 

6 

7class 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