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