Coverage for jutil/drf_exceptions.py: 46%

25 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-10-07 16:40 -0500

1import logging 

2from typing import Any 

3from django.core.exceptions import ValidationError as DjangoValidationError 

4 

5try: 

6 from rest_framework.exceptions import ValidationError as DRFValidationError # type: ignore 

7 from rest_framework.views import exception_handler as drf_exception_handler # type: ignore 

8except Exception as err: 

9 raise Exception("Using jutil.drf_exceptions requires djangorestframework installed") from err 

10 

11logger = logging.getLogger(__name__) 

12 

13 

14def transform_exception_to_drf(exception: Exception) -> Exception: 

15 """ 

16 Transform Django ValidationError into an equivalent DRF ValidationError. 

17 Note that even if this approach is not technically recommended, this is still 

18 the most convenient way to handle shared validation between Django admin and API. 

19 """ 

20 if isinstance(exception, DjangoValidationError): 20 ↛ 31line 20 didn't jump to line 31, because the condition on line 20 was never false

21 detail: Any = str(exception) 

22 if hasattr(exception, "message_dict"): 22 ↛ 24line 22 didn't jump to line 24, because the condition on line 22 was never false

23 detail = exception.message_dict 

24 elif hasattr(exception, "messages"): 

25 detail = exception.messages 

26 elif hasattr(exception, "message"): 

27 detail = exception.message 

28 else: 

29 logger.error("Unsupported ValidationError detail: %s", exception) 

30 return DRFValidationError(detail=detail) 

31 return exception 

32 

33 

34def custom_exception_handler(exc, context): 

35 """ 

36 Custom DRF exception handler which converts Django ValidationError to DRF ValidationError. 

37 Note that even if this approach is not technically recommended, this is still 

38 the most convenient way to handle shared validation between Django admin and API. 

39 

40 DRF exception handler must be set in settings.py: 

41 

42 REST_FRAMEWORK = { 

43 ... # ... 

44 ... 'EXCEPTION_HANDLER': 'jutil.drf_exceptions.custom_exception_handler', 

45 ... # ... 

46 ... } 

47 """ 

48 if isinstance(exc, DjangoValidationError): 

49 exc = transform_exception_to_drf(exc) 

50 return drf_exception_handler(exc, context)