Я знаю, что это старый нить, но добавление к ответу Рахул, вот способ, чтобы включить throttleType в сообщении:
Создайте файл с именем rest_exceptions.py
, и создать следующее:
import math
import inspect
from django.utils.encoding import force_text
from django.utils.translation import ungettext
from rest_framework import exceptions, throttling
class CustomThrottled(exceptions.Throttled):
def __init__(self, wait=None, detail=None, throttle_instance=None):
if throttle_instance is None:
self.throttle_instance = None
else:
self.throttle_instance = throttle_instance
if detail is not None:
self.detail = force_text(detail)
else:
self.detail = force_text(self.default_detail)
if wait is None:
self.wait = None
else:
self.wait = math.ceil(wait)
Здесь вы добавляете kwarg для экземпляра дросселя, что повышает исключение (если предусмотрено). Вы также можете переопределить поведение подробного сообщения и делать то, что хотите, с помощью значения wait
. Я решил не конкатенировать детали и подождать, а скорее использовать необработанное подробное сообщение.
Далее вы должны создать настраиваемое представление, которое передает дроссельную заслонку в дроссельное исключение.Создайте файл с именем rest_viewsets.py
и создать следующее:
from rest_framework import viewsets
from .rest_exceptions import CustomThrottled
class ThrottledViewSet(viewsets.ViewSet):
"""
Adds customizability to the throtted method for better clarity.
"""
throttled_exception_class = CustomThrottled
def throttled(self, request, wait, throttle_instance=None):
"""
If request is throttled, determine what kind of exception to raise.
"""
raise self.get_throttled_exception_class()(wait, detail=self.get_throttled_message(request),
throttle_instance=throttle_instance)
def get_throttled_message(self, request):
"""
Add a custom throttled exception message to pass to the user.
Note that this does not account for the wait message, which will be added at the
end of this message.
"""
return None
def get_throttled_exception_class(self):
"""
Return the throttled exception class to use.
"""
return self.throttled_exception_class
def check_throttles(self, request):
"""
Check if request should be throttled.
Raises an appropriate exception if the request is throttled.
"""
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait(), throttle_instance=throttle)
Теперь, когда у вас есть пользовательское исключение, которое будет хранить экземпляр дросселем, и Viewset, которое передаст экземпляр исключения, ваш следующий шаг заключается в реализации представление, которое наследует этот вид, а также использует один из перечисленных вами дроссельных классов. В вашем views.py
под предполагаемому зрения (так как вы не предоставили, что я буду называть его MyViewset
):
from .rest_viewsets import ThrottledViewSet
from rest_framework import throttling
class MyViewset(ThrottledViewSet):
throttle_classes = (throttling.userRateThrottle,) # Add more here as you wish
throttled_exception_class = CustomThrottled # This is the default already, but let's be specific anyway
def get_throttled_message(self, request):
"""Add a custom message to the throttled error."""
return "request limit exceeded"
На данный момент, ваше приложение будет проверять дросселей, как обычно, но будет также проходят вместе с экземпляром дроссельной заслонки. Я также переопределил сообщение дроссельной заслонки тем, что вы хотели. Теперь мы можем использовать решение, которое предоставил Рахул, с несколькими изменениями. Создание обработчика исключений:
from rest_framework.views import exception_handler
from .rest_exceptions import CustomThrottled
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
if isinstance(exc, CustomThrottled): # check that a CustomThrottled exception is raised
custom_response_data = { # prepare custom response data
'message': exc.detail,
'availableIn': '%d seconds'%exc.wait,
'throttleType': type(exc.throttle_instance).__name__
}
response.data = custom_response_data # set the custom response data on response object
return response
Вы можете легко получить доступ к любому другому атрибуту класса газа в этой точке, но вы только хотели название класса.
И последнее, но не в последнюю очередь, добавить обработчик настроек DRF:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}