diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index 66e181737..5752d7cb7 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -86,7 +86,7 @@ Note that the exception handler will only be called for responses generated by r The **base class** for all exceptions raised inside REST framework. -To provide a custom exception, subclass `APIException` and set the `.status_code` and `.default_detail` properties on the class. +To provide a custom exception, subclass `APIException` and set the `.status_code`, `.default_detail` and `.detail_key` properties on the class. For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code. You could do this like so: @@ -95,6 +95,7 @@ For example, if your API relies on a third party service that may sometimes be u class ServiceUnavailable(APIException): status_code = 503 default_detail = 'Service temporarily unavailable, try again later.' + detail_key = 'reason' ## ParseError diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py index 5f774a9f3..ece1421ac 100644 --- a/rest_framework/exceptions.py +++ b/rest_framework/exceptions.py @@ -13,9 +13,13 @@ class APIException(Exception): """ Base class for REST framework exceptions. Subclasses should provide `.status_code` and `.default_detail` properties. + Subclases can also override detail_key to provide a custom error key. + By default, django exceptions keep using 'detail' so if you want to be + consistent you'll need to also override them. """ status_code = status.HTTP_500_INTERNAL_SERVER_ERROR default_detail = '' + detail_key = 'detail' def __init__(self, detail=None): self.detail = detail or self.default_detail @@ -23,6 +27,7 @@ class APIException(Exception): def __str__(self): return self.detail + class ParseError(APIException): status_code = status.HTTP_400_BAD_REQUEST default_detail = 'Malformed request.' diff --git a/rest_framework/views.py b/rest_framework/views.py index a2668f2c0..6b3667e6e 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -62,10 +62,11 @@ def exception_handler(exc): if getattr(exc, 'wait', None): headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait - return Response({'detail': exc.detail}, + return Response({exc.detail_key: exc.detail}, status=exc.status_code, headers=headers) + # if using django's default exceptions, use detail as expected elif isinstance(exc, Http404): return Response({'detail': 'Not found'}, status=status.HTTP_404_NOT_FOUND)