Skip to content

Intercept redirects will cause ContentNotRenderedError with django-debug-toolbar 1.9 #1009

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hirokiky opened this issue Nov 15, 2017 · 5 comments

Comments

@hirokiky
Copy link

I tried newest django-debug-toolbar, 1.9.
And when I enabled Intercept Redirects and accessed a view returns 302, It returned ContentNotRenderedError:

ContentNotRenderedError at /admin/

The response content must be rendered before it can be accessed.

Request Method: 	GET
Request URL: 	http://127.0.0.1:8000/admin/
Django Version: 	1.11.7
Exception Type: 	ContentNotRenderedError
Exception Value: 	

The response content must be rendered before it can be accessed.

Exception Location: 	/tmp/venv/lib/python3.6/site-packages/django/template/response.py in content, line 129
Python Executable: 	/tmp/venv/bin/python
Python Version: 	3.6.3
Python Path: 	

['/tmp/myproj',
 '/usr/lib/python36.zip',
 '/usr/lib/python3.6',
 '/usr/lib/python3.6/lib-dynload',
 '/tmp/venv/lib/python3.6/site-packages']

Server time: 	Wed, 15 Nov 2017 11:17:34 +0000

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/admin/

Django Version: 1.11.7
Python Version: 3.6.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'debug_toolbar']
Installed Middleware:
['debug_toolbar.middleware.DebugToolbarMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/tmp/venv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/tmp/venv/lib/python3.6/site-packages/django/utils/deprecation.py" in __call__
  142.             response = self.process_response(request, response)

File "/tmp/venv/lib/python3.6/site-packages/debug_toolbar/middleware.py" in process_response
  125.         content = force_text(response.content, encoding=response.charset)

File "/tmp/venv/lib/python3.6/site-packages/django/template/response.py" in content
  129.                 'The response content must be rendered before it can be accessed.'

Exception Type: ContentNotRenderedError at /admin/
Exception Value: The response content must be rendered before it can be accessed.

Reason

This error caused by content = force_text(response.content, encoding=response.charset), accessing response.content.

In this case the response was returned by RedirectsPanel.
https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/redirects.py#L9

The panel returns SimpleTemplateResponse object. this class will raise ContentNotRenderedError when response.content was accessed before calling response.render().
like content = force_text(response.content, ...).

This error wasn't on django-debug-toolbar 1.8.
And I think this change caused it
c369384

Fix idea

Simply, we can avoid this error by adding response.render() in RedirectsPanel,
folloing here https://github.com/jazzband/django-debug-toolbar/blob/master/debug_toolbar/panels/redirects.py#L27

like this.

                # Using SimpleTemplateResponse avoids running global context processors.
                response = SimpleTemplateResponse('debug_toolbar/redirect.html', context)
                response.cookies = cookies
                response.render()

Or any other nice plan? (or this issue was not correct?)
I don't know well about codes of django-debug-toolbar, so I didn't create PR yet.
Please ask and tell me anything.

@matthiask
Copy link
Member

I don't have the time right now to think about the best way to fix this, but maybe @jdufresne has an idea? If not I'll get back to this in the next few days.

This is a regression introduced by 64ef4a3, and unfortunately there was no test to detect this :-/

@jdufresne
Copy link
Contributor

Simply, we can avoid this error by adding response.render() in RedirectsPanel

I believe this would still be a problem for DebugToolbarMiddleware for handling any other SimpleTemplateResponse/TemplateResponse. These types of responses could be returned by any view or middleware, not just django-debug-toolbar. It looks like DebugToolbarMiddleware never had support for delayed rendering. I'll add this with tests. I think the correct approach is to render the content just before manipulating it:

        # If the response supports deferred rendering and hasn't been rendered
        # yet, then ensure that it does get rendered before proceeding further.
        if hasattr(response, 'render') and callable(response.render):
            response.render()
        # Insert the toolbar in the response.
        content = force_text(response.content, encoding=response.charset)

@jdufresne
Copy link
Contributor

jdufresne commented Nov 15, 2017

After further analyzing the issue, I think @hirokiky original suggested fix is the best one. I think it is incorrect for Panel.process_resposne() to return a non-rendered response. Unlike Django middleware, panels do not have the process_template_response method to ensure that the response is eventually rendered. As I don't see a use case for panels returning non-rendered response, I don't think there is a need to add one.

@hirokiky
Copy link
Author

Thank you for your reply and fix @jdufresne and @matthiask .
I understood about the middleware.

@hirokiky
Copy link
Author

It means third party panels which returns response from process_response method should call .render() method too.
But I think there's not so much panels like intercept redirects, It won't be so big issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants