Coverage for audoma_api/views.py: 94%

99 statements  

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

1from datetime import ( 

2 date, 

3 datetime, 

4 time, 

5 timedelta, 

6) 

7from decimal import Decimal 

8 

9from audoma_api.exceptions import ( 

10 CustomBadRequestException, 

11 CustomConflictException, 

12) 

13from audoma_api.models import ( 

14 Car, 

15 ExampleFileModel, 

16 ExampleModel, 

17 ExamplePerson, 

18 Manufacturer, 

19) 

20from audoma_api.permissions import ( 

21 AlternatePermission1, 

22 AlternatePermission2, 

23 DetailPermission, 

24 ViewAndDetailPermission, 

25 ViewPermission, 

26) 

27from audoma_api.serializers import ( 

28 CarModelSerializer, 

29 ExampleFileModelSerializer, 

30 ExampleModelCreateSerializer, 

31 ExampleModelSerializer, 

32 ExampleOneFieldSerializer, 

33 ExamplePersonModelSerializer, 

34 ExampleSerializer, 

35 ManufacturerModelSerializer, 

36 MutuallyExclusiveExampleSerializer, 

37) 

38from django_filters import rest_framework as df_filters 

39from rest_framework.decorators import action 

40from rest_framework.exceptions import NotFound 

41from rest_framework.filters import SearchFilter 

42from rest_framework.parsers import MultiPartParser 

43from rest_framework.permissions import IsAuthenticated 

44from rest_framework.response import Response 

45 

46from audoma.decorators import audoma_action 

47from audoma.drf import ( 

48 mixins, 

49 viewsets, 

50) 

51from audoma.drf.filters import DocumentedTypedChoiceFilter 

52 

53 

54class ExampleViewSet( 

55 mixins.ActionModelMixin, 

56 mixins.CreateModelMixin, 

57 mixins.RetrieveModelMixin, 

58 mixins.DestroyModelMixin, 

59 mixins.ListModelMixin, 

60 viewsets.GenericViewSet, 

61): 

62 permission_classes = [ 

63 IsAuthenticated, 

64 ViewAndDetailPermission, 

65 DetailPermission, 

66 ViewPermission, 

67 AlternatePermission1 | AlternatePermission2, 

68 ] 

69 

70 serializer_class = ExampleSerializer 

71 queryset = {} 

72 

73 @action(detail=True, methods=["post"]) 

74 def detail_action(self, request, pk=None): 

75 return Response({}) # wrong 

76 

77 @action(detail=False, methods=["post"]) 

78 def non_detail_action(self, request): 

79 return Response({}) # wrong 

80 

81 

82example_choice = DocumentedTypedChoiceFilter( 

83 ExampleModel.EXAMPLE_CHOICES, "choice", lookup_expr="exact", field_name="choices" 

84) 

85 

86 

87class ExampleChoiceFilter(df_filters.FilterSet): 

88 choice = example_choice 

89 

90 class Meta: 

91 model = ExampleModel 

92 fields = [ 

93 "choice", 

94 ] 

95 

96 

97class ExampleModelViewSet( 

98 mixins.ActionModelMixin, 

99 mixins.CreateModelMixin, 

100 mixins.RetrieveModelMixin, 

101 mixins.DestroyModelMixin, 

102 mixins.ListModelMixin, 

103 viewsets.GenericViewSet, 

104): 

105 

106 permission_classes = [ 

107 IsAuthenticated, 

108 ViewAndDetailPermission, 

109 DetailPermission, 

110 ViewPermission, 

111 AlternatePermission1 | AlternatePermission2, 

112 ] 

113 

114 filterset_class = ExampleChoiceFilter 

115 serializer_class = ExampleModelSerializer 

116 queryset = ExampleModel.objects.all() 

117 

118 @audoma_action( 

119 detail=True, 

120 methods=["get"], 

121 results={"get": "GET method is not allowed"}, 

122 collectors=None, 

123 ) 

124 def detail_action(self, request, pk=None): 

125 return Response({}) # wrong 

126 

127 @action(detail=False, methods=["post"]) 

128 def non_detail_action(self, request): 

129 return Response({}) # wron 

130 

131 

132class ExamplePersonModelViewSet( 

133 mixins.ActionModelMixin, 

134 mixins.CreateModelMixin, 

135 mixins.RetrieveModelMixin, 

136 mixins.DestroyModelMixin, 

137 mixins.ListModelMixin, 

138 viewsets.GenericViewSet, 

139): 

140 permission_classes = [ 

141 IsAuthenticated, 

142 ViewAndDetailPermission, 

143 DetailPermission, 

144 ViewPermission, 

145 ] 

146 

147 serializer_class = ExamplePersonModelSerializer 

148 queryset = ExamplePerson.objects.all() 

149 

150 @action(detail=True, methods=["post"]) 

151 def detail_action(self, request, pk=None): 

152 return Response({}) 

153 

154 @action(detail=False, methods=["post"]) 

155 def non_detail_action(self, request): 

156 return Response({}) 

157 

158 

159class ExampleFileUploadViewSet( 

160 mixins.ActionModelMixin, 

161 mixins.CreateModelMixin, 

162 viewsets.GenericViewSet, 

163): 

164 serializer_class = ExampleFileModelSerializer 

165 queryset = ExampleFileModel.objects.all() 

166 

167 parser_classes = [MultiPartParser] 

168 

169 

170class ManufacturerViewSet( 

171 mixins.ActionModelMixin, 

172 mixins.BulkCreateModelMixin, 

173 mixins.UpdateModelMixin, 

174 mixins.ListModelMixin, 

175 mixins.DestroyModelMixin, 

176 mixins.BulkUpdateModelMixin, 

177 mixins.RetrieveModelMixin, 

178 viewsets.GenericViewSet, 

179): 

180 queryset = Manufacturer.objects.all() 

181 serializer_class = ManufacturerModelSerializer 

182 

183 

184class CarViewSet( 

185 mixins.ActionModelMixin, 

186 mixins.RetrieveModelMixin, 

187 mixins.ListModelMixin, 

188 viewsets.GenericViewSet, 

189): 

190 queryset = Car.objects.none() 

191 serializer_class = CarModelSerializer 

192 

193 filter_backends = [SearchFilter, df_filters.DjangoFilterBackend] 

194 

195 filterset_fields = ["engine_type"] 

196 search_fields = ["=manufacturer", "name"] 

197 

198 

199class MutuallyExclusiveViewSet( 

200 mixins.ActionModelMixin, 

201 mixins.CreateModelMixin, 

202 mixins.ListModelMixin, 

203 viewsets.GenericViewSet, 

204): 

205 serializer_class = MutuallyExclusiveExampleSerializer 

206 

207 

208class ExampleModelPermissionLessViewSet( 

209 mixins.ActionModelMixin, viewsets.GenericViewSet 

210): 

211 serializer_class = ExampleModelSerializer 

212 queryset = ExampleModel.objects.all() 

213 

214 @audoma_action( 

215 detail=True, 

216 methods=["post"], 

217 collectors={"post": ExampleModelCreateSerializer}, 

218 results={"post": {201: ExampleModelSerializer, 202: ExampleOneFieldSerializer}}, 

219 ) 

220 def detail_action(self, request, collect_serializer, pk=None): 

221 if request.data.pop("usertype", None): 

222 return collect_serializer.save(), 201 

223 return {"rate": ExampleOneFieldSerializer.RATES.LIKE}, 202 

224 

225 @audoma_action( 

226 detail=False, 

227 methods=["get"], 

228 results={"get": {200: "This is a test view", 404: "Not found"}}, 

229 ) 

230 def non_detail_action(self, request): 

231 return None, 200 

232 

233 @audoma_action( 

234 detail=False, 

235 methods=["post"], 

236 results=ExampleOneFieldSerializer, 

237 collectors=ExampleOneFieldSerializer, 

238 ) 

239 def rate_create_action(self, request, collect_serializer): 

240 return collect_serializer.save(), 201 

241 

242 @audoma_action(detail=True, methods=["get"], results=ExampleOneFieldSerializer) 

243 def specific_rate(self, request, pk=None): 

244 return {"rate": ExampleOneFieldSerializer.RATES.DISLIKIE}, 200 

245 

246 @audoma_action( 

247 detail=False, 

248 methods=["get"], 

249 results=ExampleOneFieldSerializer, 

250 errors=[CustomBadRequestException(), CustomConflictException], 

251 ) 

252 def properly_defined_exception_example(self, request): 

253 raise CustomConflictException("Some custom message, that should be accepted") 

254 

255 @audoma_action(detail=False, methods=["get"]) 

256 def proper_usage_of_common_errors(self, request): 

257 raise NotFound 

258 

259 @audoma_action( 

260 detail=False, 

261 methods=["get"], 

262 results=ExampleOneFieldSerializer, 

263 ) 

264 def improperly_defined_exception_example(self, request): 

265 raise CustomBadRequestException 

266 

267 def get_object(self): 

268 return ExampleModel( 

269 char_field="TESTChar", 

270 phone_number="+18888888822", 

271 email="test@iteo.com", 

272 url="http://localhost:8000/redoc/", 

273 boolean=False, 

274 nullboolean=None, 

275 mac_adress="96:82:2E:6B:F5:49", 

276 slug="tst", 

277 uuid="14aefe15-7c96-49b6-9637-7019c58c25d2", 

278 ip_address="192.168.10.1", 

279 integer=16, 

280 _float=12.2, 

281 decimal=Decimal("13.23"), 

282 datetime=datetime(2009, 11, 13, 10, 39, 35), 

283 date=date(2009, 11, 13), 

284 time=time(10, 39, 35), 

285 duration=timedelta(days=1), 

286 choices=1, 

287 json="", 

288 ) 

289 

290 @audoma_action( 

291 detail=True, 

292 methods=["put", "patch"], 

293 collectors=ExampleModelCreateSerializer, 

294 results=ExampleModelSerializer, 

295 ) 

296 def example_update_action(self, request, collect_serializer, pk=None): 

297 return collect_serializer.save(), 201