mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-23 15:54:16 +03:00
Use translatable error strings. Refs #2063.
This commit is contained in:
parent
3eaf92e893
commit
6cb6510132
|
@ -5,7 +5,11 @@ In addition Django's built in 403 and 404 exceptions are handled.
|
|||
(`django.http.Http404` and `django.core.exceptions.PermissionDenied`)
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext_lazy
|
||||
from rest_framework import status
|
||||
from rest_framework.compat import force_text
|
||||
import math
|
||||
|
||||
|
||||
|
@ -15,10 +19,13 @@ class APIException(Exception):
|
|||
Subclasses should provide `.status_code` and `.default_detail` properties.
|
||||
"""
|
||||
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
default_detail = 'A server error occured'
|
||||
default_detail = _('A server error occured')
|
||||
|
||||
def __init__(self, detail=None):
|
||||
self.detail = detail or self.default_detail
|
||||
if detail is not None:
|
||||
self.detail = force_text(detail)
|
||||
else:
|
||||
self.detail = force_text(self.default_detail)
|
||||
|
||||
def __str__(self):
|
||||
return self.detail
|
||||
|
@ -31,6 +38,19 @@ class APIException(Exception):
|
|||
# from rest_framework import serializers
|
||||
# raise serializers.ValidationError('Value was invalid')
|
||||
|
||||
def force_text_recursive(data):
|
||||
if isinstance(data, list):
|
||||
return [
|
||||
force_text_recursive(item) for item in data
|
||||
]
|
||||
elif isinstance(data, dict):
|
||||
return dict([
|
||||
(key, force_text_recursive(value))
|
||||
for key, value in data.items()
|
||||
])
|
||||
return force_text(data)
|
||||
|
||||
|
||||
class ValidationError(APIException):
|
||||
status_code = status.HTTP_400_BAD_REQUEST
|
||||
|
||||
|
@ -39,7 +59,7 @@ class ValidationError(APIException):
|
|||
# The details should always be coerced to a list if not already.
|
||||
if not isinstance(detail, dict) and not isinstance(detail, list):
|
||||
detail = [detail]
|
||||
self.detail = detail
|
||||
self.detail = force_text_recursive(detail)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.detail)
|
||||
|
@ -47,59 +67,77 @@ class ValidationError(APIException):
|
|||
|
||||
class ParseError(APIException):
|
||||
status_code = status.HTTP_400_BAD_REQUEST
|
||||
default_detail = 'Malformed request.'
|
||||
default_detail = _('Malformed request.')
|
||||
|
||||
|
||||
class AuthenticationFailed(APIException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
default_detail = 'Incorrect authentication credentials.'
|
||||
default_detail = _('Incorrect authentication credentials.')
|
||||
|
||||
|
||||
class NotAuthenticated(APIException):
|
||||
status_code = status.HTTP_401_UNAUTHORIZED
|
||||
default_detail = 'Authentication credentials were not provided.'
|
||||
default_detail = _('Authentication credentials were not provided.')
|
||||
|
||||
|
||||
class PermissionDenied(APIException):
|
||||
status_code = status.HTTP_403_FORBIDDEN
|
||||
default_detail = 'You do not have permission to perform this action.'
|
||||
default_detail = _('You do not have permission to perform this action.')
|
||||
|
||||
|
||||
class MethodNotAllowed(APIException):
|
||||
status_code = status.HTTP_405_METHOD_NOT_ALLOWED
|
||||
default_detail = "Method '%s' not allowed."
|
||||
default_detail = _("Method '%s' not allowed.")
|
||||
|
||||
def __init__(self, method, detail=None):
|
||||
self.detail = detail or (self.default_detail % method)
|
||||
if detail is not None:
|
||||
self.detail = force_text(detail)
|
||||
else:
|
||||
self.detail = force_text(self.default_detail) % method
|
||||
|
||||
|
||||
class NotAcceptable(APIException):
|
||||
status_code = status.HTTP_406_NOT_ACCEPTABLE
|
||||
default_detail = "Could not satisfy the request Accept header"
|
||||
default_detail = _('Could not satisfy the request Accept header')
|
||||
|
||||
def __init__(self, detail=None, available_renderers=None):
|
||||
self.detail = detail or self.default_detail
|
||||
if detail is not None:
|
||||
self.detail = force_text(detail)
|
||||
else:
|
||||
self.detail = force_text(self.default_detail)
|
||||
self.available_renderers = available_renderers
|
||||
|
||||
|
||||
class UnsupportedMediaType(APIException):
|
||||
status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
|
||||
default_detail = "Unsupported media type '%s' in request."
|
||||
default_detail = _("Unsupported media type '%s' in request.")
|
||||
|
||||
def __init__(self, media_type, detail=None):
|
||||
self.detail = detail or (self.default_detail % media_type)
|
||||
if detail is not None:
|
||||
self.detail = force_text(detail)
|
||||
else:
|
||||
self.detail = force_text(self.default_detail) % media_type
|
||||
|
||||
|
||||
class Throttled(APIException):
|
||||
status_code = status.HTTP_429_TOO_MANY_REQUESTS
|
||||
default_detail = 'Request was throttled.'
|
||||
extra_detail = " Expected available in %d second%s."
|
||||
default_detail = _('Request was throttled.')
|
||||
extra_detail = ungettext_lazy(
|
||||
'Expected available in %(wait)d second.',
|
||||
'Expected available in %(wait)d seconds.',
|
||||
'wait'
|
||||
)
|
||||
|
||||
def __init__(self, wait=None, detail=None):
|
||||
if detail is not None:
|
||||
self.detail = force_text(detail)
|
||||
else:
|
||||
self.detail = force_text(self.default_detail)
|
||||
|
||||
if wait is None:
|
||||
self.detail = detail or self.default_detail
|
||||
self.wait = None
|
||||
else:
|
||||
format = (detail or self.default_detail) + self.extra_detail
|
||||
self.detail = format % (wait, wait != 1 and 's' or '')
|
||||
self.wait = math.ceil(wait)
|
||||
self.detail += ' ' + force_text(
|
||||
self.extra_detail % {'wait': self.wait}
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user