mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +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`)
 | 
					(`django.http.Http404` and `django.core.exceptions.PermissionDenied`)
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					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 import status
 | 
				
			||||||
 | 
					from rest_framework.compat import force_text
 | 
				
			||||||
import math
 | 
					import math
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,10 +19,13 @@ class APIException(Exception):
 | 
				
			||||||
    Subclasses should provide `.status_code` and `.default_detail` properties.
 | 
					    Subclasses should provide `.status_code` and `.default_detail` properties.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
 | 
					    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):
 | 
					    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):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.detail
 | 
					        return self.detail
 | 
				
			||||||
| 
						 | 
					@ -31,6 +38,19 @@ class APIException(Exception):
 | 
				
			||||||
# from rest_framework import serializers
 | 
					# from rest_framework import serializers
 | 
				
			||||||
# raise serializers.ValidationError('Value was invalid')
 | 
					# 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):
 | 
					class ValidationError(APIException):
 | 
				
			||||||
    status_code = status.HTTP_400_BAD_REQUEST
 | 
					    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.
 | 
					        # The details should always be coerced to a list if not already.
 | 
				
			||||||
        if not isinstance(detail, dict) and not isinstance(detail, list):
 | 
					        if not isinstance(detail, dict) and not isinstance(detail, list):
 | 
				
			||||||
            detail = [detail]
 | 
					            detail = [detail]
 | 
				
			||||||
        self.detail = detail
 | 
					        self.detail = force_text_recursive(detail)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return str(self.detail)
 | 
					        return str(self.detail)
 | 
				
			||||||
| 
						 | 
					@ -47,59 +67,77 @@ class ValidationError(APIException):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ParseError(APIException):
 | 
					class ParseError(APIException):
 | 
				
			||||||
    status_code = status.HTTP_400_BAD_REQUEST
 | 
					    status_code = status.HTTP_400_BAD_REQUEST
 | 
				
			||||||
    default_detail = 'Malformed request.'
 | 
					    default_detail = _('Malformed request.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AuthenticationFailed(APIException):
 | 
					class AuthenticationFailed(APIException):
 | 
				
			||||||
    status_code = status.HTTP_401_UNAUTHORIZED
 | 
					    status_code = status.HTTP_401_UNAUTHORIZED
 | 
				
			||||||
    default_detail = 'Incorrect authentication credentials.'
 | 
					    default_detail = _('Incorrect authentication credentials.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NotAuthenticated(APIException):
 | 
					class NotAuthenticated(APIException):
 | 
				
			||||||
    status_code = status.HTTP_401_UNAUTHORIZED
 | 
					    status_code = status.HTTP_401_UNAUTHORIZED
 | 
				
			||||||
    default_detail = 'Authentication credentials were not provided.'
 | 
					    default_detail = _('Authentication credentials were not provided.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PermissionDenied(APIException):
 | 
					class PermissionDenied(APIException):
 | 
				
			||||||
    status_code = status.HTTP_403_FORBIDDEN
 | 
					    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):
 | 
					class MethodNotAllowed(APIException):
 | 
				
			||||||
    status_code = status.HTTP_405_METHOD_NOT_ALLOWED
 | 
					    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):
 | 
					    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):
 | 
					class NotAcceptable(APIException):
 | 
				
			||||||
    status_code = status.HTTP_406_NOT_ACCEPTABLE
 | 
					    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):
 | 
					    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
 | 
					        self.available_renderers = available_renderers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UnsupportedMediaType(APIException):
 | 
					class UnsupportedMediaType(APIException):
 | 
				
			||||||
    status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
 | 
					    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):
 | 
					    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):
 | 
					class Throttled(APIException):
 | 
				
			||||||
    status_code = status.HTTP_429_TOO_MANY_REQUESTS
 | 
					    status_code = status.HTTP_429_TOO_MANY_REQUESTS
 | 
				
			||||||
    default_detail = 'Request was throttled.'
 | 
					    default_detail = _('Request was throttled.')
 | 
				
			||||||
    extra_detail = " Expected available in %d second%s."
 | 
					    extra_detail = ungettext_lazy(
 | 
				
			||||||
 | 
					        'Expected available in %(wait)d second.',
 | 
				
			||||||
 | 
					        'Expected available in %(wait)d seconds.',
 | 
				
			||||||
 | 
					        'wait'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, wait=None, detail=None):
 | 
					    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:
 | 
					        if wait is None:
 | 
				
			||||||
            self.detail = detail or self.default_detail
 | 
					 | 
				
			||||||
            self.wait = None
 | 
					            self.wait = None
 | 
				
			||||||
        else:
 | 
					        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.wait = math.ceil(wait)
 | 
				
			||||||
 | 
					            self.detail += ' ' + force_text(
 | 
				
			||||||
 | 
					                self.extra_detail % {'wait': self.wait}
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user