Django Rest Framework:从mixin的调度方法返回响应

问题描述 投票:1回答:2

为了与松弛交互,服务器需要能够基于某些加密哈希来验证请求。如果此检查返回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?解决此问题的最简单方法是什么?

django django-rest-framework dispatch django-drf-renderer
2个回答
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

0
投票

首先是解决方案:您的第二种方法很好,您只需要实例化JSONResponse类:

response.accepted_renderer = JSONRenderer()

背景:

  • WSGIHandler继承的Django Basehandler调用response.render()呈现响应
  • DRF Response(从SimpleTemplateResponse继承)对象具有render方法,该方法将调用委派给rendered_content属性
  • [在初始内容协商阶段,根据客户端传递的DEFAULT_RENDERER_CLASSES / APIView.renderer_classes设置和Aceept标头设置渲染器;所选渲染器在HttpRequest对象中设置为accepted_renderer,媒体类型设置为request.accepted_media_type属性
  • 如果渲染器需要任何额外的上下文,则Response对象还需要renderer_context属性;例如,views.APIView将当前视图,请求和参数设置为renderer_context dict

现在应该很清楚,为什么需要带有Response对象的属性-获取渲染器,媒体类型并传递所选渲染器可能需要的任何其他上下文。


You've added an answer,在其中设置上述属性,然后从渲染器返回一个空的dict作为响应。如果您要遵循这条路线,则更简单,更简洁的选择是创建Response的子类,并从render方法返回空字典,例如:]]

class EmptyReponse(rest_framework.response.Response):

     def render(self):
         return {}

现在只需要返回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)
© www.soinside.com 2019 - 2024. All rights reserved.