switch to using format strings in error messages; raise NotFound when pagination fails to provide a more useful error message

This commit is contained in:
Craig Blaszczyk 2015-01-07 11:41:06 +00:00
parent 7913947757
commit 9b4177b6ea
2 changed files with 22 additions and 20 deletions

View File

@ -7,8 +7,7 @@ In addition Django's built in 403 and 404 exceptions are handled.
from __future__ import unicode_literals
from django.utils import six
from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from django.utils.translation import ugettext_lazy as _, ungettext
from rest_framework import status
import math
@ -96,13 +95,13 @@ class NotFound(APIException):
class MethodNotAllowed(APIException):
status_code = status.HTTP_405_METHOD_NOT_ALLOWED
default_detail = _("Method '%s' not allowed.")
default_detail = _("Method {method} not allowed.")
def __init__(self, method, detail=None):
if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail) % method
self.detail = force_text(self.default_detail).format(method=method)
class NotAcceptable(APIException):
@ -119,23 +118,22 @@ class NotAcceptable(APIException):
class UnsupportedMediaType(APIException):
status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
default_detail = _("Unsupported media type '%s' in request.")
default_detail = _("Unsupported media type '{media_type}' in request.")
def __init__(self, media_type, detail=None):
if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail) % media_type
self.detail = force_text(self.default_detail).format(
media_type=media_type
)
class Throttled(APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_detail = _('Request was throttled.')
extra_detail = ungettext_lazy(
'Expected available in %(wait)d second.',
'Expected available in %(wait)d seconds.',
'wait'
)
extra_detail_singular = 'Expected available in {wait} second.'
extra_detail_plural = 'Expected available in {wait} seconds.'
def __init__(self, wait=None, detail=None):
if detail is not None:
@ -147,6 +145,8 @@ class Throttled(APIException):
self.wait = None
else:
self.wait = math.ceil(wait)
self.detail += ' ' + force_text(
self.extra_detail % {'wait': self.wait}
)
self.detail += ' ' + force_text(ungettext(
self.extra_detail_singular.format(wait=self.wait),
self.extra_detail_plural.format(wait=self.wait),
self.wait
))

View File

@ -10,6 +10,7 @@ from django.shortcuts import get_object_or_404 as _get_object_or_404
from django.utils import six
from django.utils.translation import ugettext as _
from rest_framework import views, mixins
from rest_framework.exceptions import NotFound
from rest_framework.settings import api_settings
@ -119,15 +120,16 @@ class GenericAPIView(views.APIView):
if page == 'last':
page_number = paginator.num_pages
else:
raise Http404(_("Choose a valid page number. Page numbers must be a whole number, or must be the string 'last'."))
raise NotFound(_("Choose a valid page number. Page numbers must be a whole number, or must be the string 'last'."))
page_number = -1
try:
page = paginator.page(page_number)
except InvalidPage as exc:
error_format = _('Invalid page (%(page_number)s): %(message)s')
raise Http404(error_format % {
'page_number': page_number,
'message': six.text_type(exc)
})
error_format = _('Invalid page ({page_number}): {message}')
raise NotFound(error_format.format(
page_number=page_number, message=six.text_type(exc)
))
return page