I am creating Django middleware for blocking a user when (s)he gets throttled more than 5 times but I am getting ContentNotRenderedError.
Traceback (most recent call last):
  File "/home/user/Application/utilities/anaconda3/envs/app/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/user/Application/utilities/anaconda3/envs/app/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "/home/user/Application/utilities/anaconda3/envs/app/lib/python3.8/site-packages/django/middleware/common.py", line 113, in process_response
    response.headers['Content-Length'] = str(len(response.content))
  File "/home/user/Application/utilities/anaconda3/envs/app/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
Example return of handle_blocking function:
return Response(
    data='User is blocked, please contact the support team.',
    status=status.HTTP_403_FORBIDDEN
)
It works when I remove the middleware and don't use the Response class(return the self.get_response(request) instead).
I am unable to figure out the error. What am I doing wrong?
If you really want to return a Response instance, you need to set some properties before returning it:
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
You need to do the same also in your handle_blocking implementation, for example:
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
These properties are generally set by the api_view decorator that cannot be used with middlewares, so you must set them manually.
Go for 'reponse.data' if you are using RequestFactory. It worked in my case to fetch respose data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With