{{{
from django.conf.urls import url
from django.core.exceptions import PermissionDenied
from django.views.generic import TemplateView
class PermissionDeniedView(TemplateView):
template_name = '403.html'
handler403 = PermissionDeniedView.as_view()
def my_view(request):
raise PermissionDenied
urlpatterns = [
url(r'^$', my_view),
]
}}}
Traceback:
{{{
Traceback (most recent call last):
File "/usr/lib64/python2.7/wsgiref/handlers.py", line 86, in run
self.finish_response()
File "/usr/lib64/python2.7/wsgiref/handlers.py", line 127, in
finish_response
for data in self.result:
File "/home/foo/.virtualenvs/bar/lib/python2.7/site-
packages/django/template/response.py", line 171, in __iter__
raise ContentNotRenderedError('The response content must be '
ContentNotRenderedError: The response content must be rendered before it
can be iterated over.
[20/May/2015 07:26:25]"GET / HTTP/1.1" 500 59
Traceback (most recent call last):
File "/usr/lib64/python2.7/SocketServer.py", line 599, in
process_request_thread
self.finish_request(request, client_address)
File "/usr/lib64/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/home/foo/.virtualenvs/bar/lib/python2.7/site-
packages/django/core/servers/basehttp.py", line 102, in __init__
super(WSGIRequestHandler, self).__init__(*args, **kwargs)
File "/usr/lib64/python2.7/SocketServer.py", line 655, in __init__
self.handle()
File "/home/foo/.virtualenvs/bar/lib/python2.7/site-
packages/django/core/servers/basehttp.py", line 182, in handle
handler.run(self.server.get_app())
File "/usr/lib64/python2.7/wsgiref/handlers.py", line 92, in run
self.close()
File "/usr/lib64/python2.7/wsgiref/simple_server.py", line 33, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
}}}
One workaround is to force TemplateResponse to render itself:
{{{
class PermissionDeniedView(TemplateView):
template_name = '403.html'
def dispatch(self, request, *args, **kwargs):
response = super(PermissionDeniedView, self).dispatch(request,
*args, **kwargs)
response.render()
return response
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24829>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* version: 1.8 => master
* needs_docs: => 0
* type: Bug => New feature
* stage: Unreviewed => Accepted
Comment:
I'm wondering if you have a compelling use case for class-based views as
error handlers? Your example reproduces the default view as far as I can
tell. I'm not sure what changes would be required to support this, but I'd
think it would be nice to keep the error handling code as simple as
possible. That said, if we decide not to fix this we should at least
document the restriction.
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:1>
Comment (by nonZero):
Regarding use case - our "permission denied" page includes the complete
site layout - including navigation and user information resolved at a site
wide mixin used also in the PermissionDeniedView.
Examining the source code of
[https://github.com/django/django/blob/d17a035132c4ddba51d57286b2185bc459f69067/django/template/response.py#L173
SimpleTemplateResponse], one solution could be removing
ContentNotRenderedError, and call self.render() instead of raising it:
{{{
if not self._is_rendered:
self.render()
}}}
Why is ContentNotRenderedError needed?
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:2>
Comment (by timgraham):
Did you try making the change you suggested and then looking at what tests
fail? That usually gives some insight.
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:3>
* status: new => assigned
* owner: nobody => ana-balica
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:4>
* has_patch: 0 => 1
* needs_tests: 0 => 1
Comment:
[https://github.com/django/django/pull/4777 PR] which needs tests.
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:5>
* needs_better_patch: 0 => 1
* needs_tests: 1 => 0
Comment:
Now has tests, but needs some other improvements.
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:6>
Comment (by nonZero):
Regarding the suggested fix, instead of fixing the handler, shouldn't this
be considered as a TemplateResponse / TemplateView problem?
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:7>
* needs_better_patch: 1 => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:8>
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:9>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"2f615b10e6330d27dccbd770a4628200044acf70" 2f615b10]:
{{{
#!CommitTicketReference repository=""
revision="2f615b10e6330d27dccbd770a4628200044acf70"
Fixed #24829 -- Allowed use of TemplateResponse in view error handlers.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:10>
Comment (by Claude Paroz <claude@…>):
In [changeset:"742ea51413b3aab07c6afbfd1d52c1908ffcb510" 742ea514]:
{{{
#!CommitTicketReference repository=""
revision="742ea51413b3aab07c6afbfd1d52c1908ffcb510"
Refs #24829 -- Made TemplateResponse.content available sooner in exception
context
Thanks Tim Graham for the initial patch.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:11>
Comment (by Tim Graham <timograham@…>):
In [changeset:"bff5ccff7501d7bafb53d6110e311882e716bee5" bff5ccff]:
{{{
#!CommitTicketReference repository=""
revision="bff5ccff7501d7bafb53d6110e311882e716bee5"
Refs #24829 -- Removed TemplateResponse rendering in
BaseHandler.get_response().
Obsolete since 742ea51413b3aab07c6afbfd1d52c1908ffcb510.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/24829#comment:12>