Down voted the answer above as it doesn't work for me.
The neighbor answer isn't helpful, too.
Both still return ContentNotRenderedError
without manual call of the .render()
method.
Tested with Python 3.8, Django 2.2, DRF 3.12.1.
The working mimicking middleware method for me is:
from rest_framework.views import APIView
# ... in the middleware class
def __call__(self, request):
try:
# Middleware logic before calling a view.
except APIException as err:
# No DRF auto-wrap out of view, so let's do it manually.
response = some_exception_handler(err, {})
return self.django_response(request, response)
return self.get_response(request)
def django_response(self, request: HttpRequest, resp: Response) -> HttpResponse:
view = APIView()
# copy-pasted from APIView.dispatch
view.headers = view.default_response_headers
return view.finalize_response(request, resp).render()
Docs investigation
To support my doubts about other solutions, here's the problem with an exception in middleware before the view has been called.
I bet the .render()
method cannot be called automatically, cause the docs say:
There are three circumstances under which a TemplateResponse will be rendered:
- When the TemplateResponse instance is explicitly rendered, using the SimpleTemplateResponse.render() method.
- When the content of the response is explicitly set by assigning response.content.
- After passing through template response middleware, but before passing through response middleware.
In our case only the 3-rd option matches. So, what is that "template response middleware"? There's only one similar thing in the docs:
process_template_response() is called just after the view has finished executing, if the response instance has a render() method, indicating that it is a TemplateResponse or equivalent.
But we haven't reached the view being executed! That's why the .render()
method won't be called in our case.
@renderer_classes
decorator... – Piane