为了与松弛交互,服务器需要能够基于某些加密哈希来验证请求。如果此检查返回false,则服务器应以400响应。将其作为mixin这样做是明智的:
class SlackValidationMixin:
def dispatch(self, request, *args, **kwargs):
if validate_slack_request(request):
return super().dispatch(request, *args, **kwargs)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
这给出了错误“未在响应上设置accepted_renderer” 基于一个SO问题,我添加了以下内容:
class SlackValidationMixin:
def dispatch(self, request, *args, **kwargs):
if validate_slack_request(request):
return super().dispatch(request, *args, **kwargs)
else:
response = Response(status=status.HTTP_400_BAD_REQUEST)
response.accepted_renderer = JSONRenderer
response.accepted_media_type = "application/json"
response.renderer_context = {}
return response
但这会导致错误:AttributeError: 'NoneType' object has no attribute 'get_indent'
为什么它只需要一个HTTP状态代码,却没有其他数据,为什么还需要一个accepted_renderer?解决这个问题的最简单方法是什么?
以下回答建议使EmptyResponse对象从Response继承:
Traceback (most recent call last):
File "path/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "path/lib/python3.8/site-packages/django/utils/deprecation.py", line 96, in __call__
response = self.process_response(request, response)
File "path/lib/python3.8/site-packages/django/middleware/common.py", line 106, in process_response
if response.status_code == 404:
AttributeError: 'dict' object has no attribute 'status_code'
答案 0 :(得分:2)
首先是解决方案:您的第二种方法很好,您只需实例化JSONResponse
类(DRF在get_renderers
的{{1}}方法中做到这一点)
views.APIView
背景:
response.accepted_renderer = JSONRenderer()
(继承自WSGIHandler
)调用Basehandler
来呈现响应response.render()
(从Response
继承)对象具有一个SimpleTemplateResponse
方法,该方法通过render
属性(称为rendered_content
方法)获取呈现的内容。呈现器以及传递的数据,媒体类型和上下文)render
/ DEFAULT_RENDERER_CLASSES
设置和APIView.renderer_classes
标头设置渲染器;所选渲染器在Aceept
对象中设置为HttpRequest
,媒体类型设置为accepted_renderer
属性request.accepted_media_type
对象也需要Response
属性;例如,renderer_context
将当前视图,请求和参数设置为views.APIView
字典现在应该很清楚,为什么需要带有renderer_context
对象的属性-获取渲染器,媒体类型并传递所选渲染器可能需要的任何额外上下文。
You've added an answer,在其中设置上述属性,然后从渲染器返回空字典作为响应。如果您要遵循这条路线,则更简单,更简洁的选择是创建Response
的子类,并从Response
方法返回空字典,例如:
render
现在仅返回class EmptyResponse(rest_framework.response.Response):
def render(self):
# You can have your own rendered content here
self.content = b''
return self
对象即可,无需添加与渲染器相关的属性:
EmptyResponse
现在,除非您要添加一些自定义内容,否则不需要延迟的渲染;您可以直接返回class SlackValidationMixin:
def dispatch(self, request, *args, **kwargs):
if validate_slack_request(request):
return super().dispatch(request, *args, **kwargs)
else:
return EmptyResponse(status=status.HTTP_400_BAD_REQUEST)
对象:
HttpResponse
如果需要,可以在初始化from django.http import HttpResponse
class SlackValidationMixin:
def dispatch(self, request, *args, **kwargs):
if validate_slack_request(request):
return super().dispatch(request, *args, **kwargs)
else:
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
时传递content
(以字节为单位)。但是如果由于某些原因需要延迟渲染,则需要使用HttpResponse
。
答案 1 :(得分:0)
创建不返回任何内容的渲染器似乎可以使其正常工作。如果这是“正确”的方式,我会感到惊讶,但它可以完成工作。
class NoneRenderer(BaseRenderer):
def render(self, *args, **kwargs):
return {}
class SlackValidationMixin:
def dispatch(self, request, *args, **kwargs):
if validate_slack_request(request):
return super().dispatch(request, *args, **kwargs)
else:
response = Response(status=status.HTTP_400_BAD_REQUEST)
response.accepted_renderer = NoneRenderer
response.accepted_media_type = "*/*"
response.renderer_context = {}
return response