Aje*_*ani 5 python django rest throttling django-rest-framework
我正在使用DRF进行休息,所以现在我正在对我的apis进行限制.为此,我创建了以下节流范围
userRateThrottle
anonRateThrottle
burstRateThrottle
perViewsThrottles(随视图而变化)
目前我得到的回应低于:
{"detail":"Request was throttled. Expected available in 32.0 seconds."}
我想回复这样的事情:
{"message":"request limit exceeded","availableIn":"32.0 seconds","throttleType":"type"}
DRF文档中没有任何内容可用于自定义.如何根据要求自定义我的回复?
Rah*_*pta 14
为此,您可以实现自定义异常处理函数,以便在出现Throttled异常时返回自定义响应.
from rest_framework.views import exception_handler
from rest_framework.exceptions import Throttled
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, Throttled): # check that a Throttled exception is raised
custom_response_data = { # prepare custom response data
'message': 'request limit exceeded',
'availableIn': '%d seconds'%exc.wait
}
response.data = custom_response_data # set the custom response data on response object
return response
Run Code Online (Sandbox Code Playgroud)
然后,您需要将此自定义异常处理程序添加到DRF设置中.
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
Run Code Online (Sandbox Code Playgroud)
我认为在throttleType不更改某些DRF代码的情况下知道这一点有点困难,因为Throttled在任何Throttle类限制请求的情况下DRF会引发异常.没有信息被传递到Throttled哪个异常throttle_class是提高该异常.
您可以通过覆盖throttled视图的方法来更改限制响应的消息。例如:
from rest_framework.exceptions import Throttled
class SomeView(APIView):
def throttled(self, request, wait):
raise Throttled(detail={
"message":"request limit exceeded",
"availableIn":f"{wait} seconds",
"throttleType":"type"
})
Run Code Online (Sandbox Code Playgroud)
我知道这是一个旧线程,但添加到 Rahul 的答案中,这里有一种在消息中包含throttleType 的方法:
您首先需要重写 Throttled 异常类:
创建一个名为 的文件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)
Run Code Online (Sandbox Code Playgroud)
在这里,您为引发异常的节流实例添加一个 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)
Run Code Online (Sandbox Code Playgroud)现在您有了一个将存储节流实例的自定义异常,以及一个将该实例传递给异常的视图集,下一步是实现一个继承此视图集的视图,并且还使用您列出的节流类之一。在您的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"
Run Code Online (Sandbox Code Playgroud)此时,您的应用程序将像往常一样检查节流阀,但也会传递节流阀实例。我还按照您想要的方式覆盖了节流消息。我们现在可以利用 Rahul 提供的解决方案,并进行一些修改。创建自定义异常处理程序:
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
Run Code Online (Sandbox Code Playgroud)
此时,您可以轻松访问节流阀类的任何其他属性,但您只需要类名称。
最后但并非最不重要的一点是,将您的处理程序添加到 DRF 设置中:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
3292 次 |
| 最近记录: |