Hide keyboard shortcuts

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

1import logging 

2from typing import Any 

3 

4from django.core.exceptions import ValidationError as DjangoValidationError 

5from rest_framework.exceptions import ValidationError as DRFValidationError 

6from rest_framework.views import exception_handler as drf_exception_handler 

7 

8logger = logging.getLogger(__name__) 

9 

10 

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

12 """ 

13 Transform Django ValidationError into an equivalent DRF ValidationError. 

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

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

16 """ 

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

18 detail: Any = str(exception) 

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

20 detail = exception.message_dict 

21 elif hasattr(exception, "messages"): 

22 detail = exception.messages 

23 elif hasattr(exception, "message"): 

24 detail = exception.message 

25 else: 

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

27 return DRFValidationError(detail=detail) 

28 return exception 

29 

30 

31def custom_exception_handler(exc, context): 

32 """ 

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

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

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

36 

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

38 

39 REST_FRAMEWORK = { 

40 ... # ... 

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

42 ... # ... 

43 ... } 

44 """ 

45 if isinstance(exc, DjangoValidationError): 

46 exc = transform_exception_to_drf(exc) 

47 return drf_exception_handler(exc, context)