ContentNotRenderedError:响应内容必须先渲染后才能访问(Django 中间件)

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

我正在创建 Django 中间件,用于在用户被限制超过 5 次时阻止用户,但我得到了

ContentNotRenderedError

完整错误消息:

Traceback (most recent call last):
  File "/home/raptor/Application/utilities/anaconda3/envs/slic4rapi/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/raptor/Application/utilities/anaconda3/envs/slic4rapi/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "/home/raptor/Application/utilities/anaconda3/envs/slic4rapi/lib/python3.8/site-packages/django/middleware/common.py", line 113, in process_response
    response.headers['Content-Length'] = str(len(response.content))
  File "/home/raptor/Application/utilities/anaconda3/envs/slic4rapi/lib/python3.8/site-packages/django/template/response.py", line 126, in content
    raise ContentNotRenderedError(
django.template.response.ContentNotRenderedError: The response content must be rendered before it can be accessed.
[22/Mar/2022 11:55:03] "GET /api/v1/userdetail/ HTTP/1.1" 500 84321

中间件类

class BlockMiddleware:
    
    def __init__(self, get_response):
        self.get_response = get_response
        # some other variables
    
    def __call__(self, request):
        # handle_blocking will return "None" if user can access application else "rest_framework.response.Response" object
        blocking_res = self.handle_blocking(request)
        if blocking_res:
            return blocking_res

        response = self.get_response(request)
        # logic for counting how many throttles have left
        # then
        if throttles_left <= 0:
            return Response(
                    data='User is blocked due to exceeding throttles limit.',
                    status=status.HTTP_403_FORBIDDEN
                )
        else:
            return response

handle_blocking
函数的返回示例:

return Response(
    data='User is blocked, please contact the support team.',
    status=status.HTTP_403_FORBIDDEN
)

当我删除中间件并且不使用

Response
类(而是返回 self.get_response(request) )时,它就可以工作。 我无法找出错误。我做错了什么?

django django-rest-framework django-middleware
2个回答
8
投票

如果你确实想返回一个

Response
实例,你需要在返回之前设置一些属性:

from rest_framework.renderers import JSONRenderer

class BlockMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        blocking_res = self.handle_blocking(request)
        if blocking_res:
            return blocking_res

        response = self.get_response(request)
        if throttles_left <= 0:
            response = Response(
               data='User is blocked due to exceeding throttles limit.',
               status=status.HTTP_403_FORBIDDEN
            )
            response.accepted_renderer = JSONRenderer()
            response.accepted_media_type = "application/json"
            response.renderer_context = {}
            response.render()
            return response
        else:
            return response

您也需要在

handle_blocking
实现中执行相同的操作,例如:

from rest_framework.renderers import JSONRenderer
response = Response(
    data='User is blocked, please contact the support team.',
    status=status.HTTP_403_FORBIDDEN
)
response.accepted_renderer = JSONRenderer()
response.accepted_media_type = "application/json"
response.renderer_context = {}
response.render()
return response

这些属性通常由

api_view
装饰器设置,不能与中间件一起使用,因此必须手动设置它们。


0
投票

如果您使用的是 RequestFactory,请选择“reponse.data”。在我的例子中,它可以获取响应数据。

© www.soinside.com 2019 - 2024. All rights reserved.