如何从django自定义中间件类返回rest_framework.response对象?

Adi*_*lik 26 django django-middleware django-rest-framework

我正在尝试编写一个确保用户登录的中间件类.但问题是这个中间件类只适用于一小组视图,这些视图返回DRF的Response对象而不是HTTPResponse对象,这些视图也是装饰用api_view.

因此,当我尝试从中间ware类返回一个Response对象时,它会引发此错误.

 assert renderer, ".accepted_renderer not set on Response"
AssertionError: .accepted_renderer not set on Response
Run Code Online (Sandbox Code Playgroud)

我在SO上搜索了一下,我猜错误与api_view装饰器有某种关系.但我对如何解决这个问题很困惑.

任何帮助表示赞赏.:)

Jor*_*dan 24

我刚刚遇到这个问题.此解决方案不使用Django Rest Framework响应,但如果您的服务器只返回JSON,则此解决方案可能适合您.

django 1.7中的新功能是JSONResponse响应类型.

https://docs.djangoproject.com/en/1.7/ref/request-response/#jsonresponse-objects

在中间件中,您可以返回这些响应,而不必拥有所有"没有接受的渲染器"和"响应没有属性编码"错误.

它与DRF响应的格式非常相似

导入如下: from django.http import JsonResponse

以及如何使用它:

return JsonResponse({'error': 'Some error'}, status=401)

希望这会帮助你!

  • @niren我不能肯定地说,但我假设是因为在视图函数周围使用了```@spi_view```装饰器.你不能在中间件函数周围使用它,我猜是Response依赖于它.它也是djangos SimpleTemplateResponse的子类,我认为它在中间件中也不行.虽然这个答案不是100%. (3认同)

A. *_*arr 11

我通过模仿其他框架的意见如何修补响应对象与此解决我自己accepted_renderer,accepted_media_typerenderer_context.在我的情况下,我只想使用rest frameworks Response类返回401响应,部分原因是我的测试在调用self.client.get(...)和断言时期望休息框架响应response.data.

其他用例可能要求您提供其他信息renderer_context或使用其他信息accepted_renderer.

from rest_framework import status
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response

class MiddlewareClass(object):

    def __init__(self, get_response):
        self.get_response = get_response

    def unauthorized_response(self, request):
        response = Response(
            {"detail": "This action is not authorized"},
            content_type="application/json",
            status=status.HTTP_401_UNAUTHORIZED,
        )
        response.accepted_renderer = JSONRenderer()
        response.accepted_media_type = "application/json"
        response.renderer_context = {}

        return response

    def __call__(self, request: HttpRequest):
        if not self.authorized(request):
            return self.unauthorized_response(request)
        return self.get_response(request)
Run Code Online (Sandbox Code Playgroud)