question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Preview mode doesn't work under WSGI/Gunicorn

See original GitHub issue

Issue Summary

Attempt to preview any page results in exception.

Steps to Reproduce

  1. Open any page in the WagTail CMS for editing
  2. Click Preview button

Site is running under nginx/gunicorn. When I run Django development server, this problem doesn’t happen, preview works as expected. This is clearly related to gunicorn, but when I run local instance of gunicorn, it doesn’t happen either. Only on the remote site.

It seems that tricks that Wagtail uses to load preview in a new window causes the problem.

After reading Wagtail source code I found this:

        preview_mode = request.GET.get('mode', page.default_preview_mode)
        response = page.serve_preview(page.dummy_request(request), preview_mode)
        response['X-Wagtail-Preview'] = 'ok'
        return response

in wagtail/wagtailadmin/views/pages.py

Apparently, differences in requests under local django devserver and gunicorn causes some malfunction in the Django authentication middleware and it fails to load currently logged in user while in preview mode.

Since this happens only in WagTail preview and all other views and dependencies functioned perfectly well in this setup for years, I assume this is a Wagtail bug.

I have “fixed” this issue in my case by changing the line from: response = page.serve_preview(page.dummy_request(request), preview_mode) to: response = page.serve_preview(request, preview_mode) On line 562 in wagtail/wagtailadmin/views/pages.py

I see that master branch uses the same dummy request technique that probably will also fail when running under gunicorn.

Technical details

AttributeError at /cms/pages/29/edit/preview/
'WSGIRequest' object has no attribute 'user'

Request Method: POST
Request URL: https://staging.royalorchard.com/cms/pages/29/edit/preview/
Django Version: 1.10.6
Python Executable: /home/rolc/.virtualenvs/dev/bin/python3
Python Version: 3.5.2
Python Path: ['/home/rolc/dev', '/home/rolc/.virtualenvs/dev/bin', '/home/rolc/.virtualenvs/dev/lib/python35.zip', '/home/rolc/.virtualenvs/dev/lib/python3.5', '/home/rolc/.virtualenvs/dev/lib/python3.5/plat-x86_64-linux-gnu', '/home/rolc/.virtualenvs/dev/lib/python3.5/lib-dynload', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages']
Server time: Fri, 14 Apr 2017 03:21:22 -0400
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.messages',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.humanize',
 'django.contrib.staticfiles',
 'django.contrib.admindocs',
 'django.contrib.flatpages',
 'tagging',
 'django_extensions',
 'filebrowser',
 'crispy_forms',
 'floppyforms',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'reversion',
 'papertrail',
 'wagtail.wagtailforms',
 'wagtail.wagtailredirects',
 'wagtail.wagtailembeds',
 'wagtail.wagtailsites',
 'wagtail.wagtailusers',
 'wagtail.wagtailsnippets',
 'wagtail.wagtaildocs',
 'wagtail.wagtailimages',
 'wagtail.wagtailsearch',
 'wagtail.wagtailadmin',
 'wagtail.wagtailcore',
 'wagtail.contrib.table_block',
 'modelcluster',
 'taggit',
 'taggit_templatetags2',
 'royal_orchard.users',
 'royal_orchard.reports',
 'royal_orchard.documents',
 'royal_orchard.emails',
 'royal_orchard.blog',
 'royal_orchard.reservations',
 'royal_orchard.vendors',
 'royal_orchard.flickr',
 'royal_orchard.search',
 'royal_orchard.userpages',
 'tinymce',
 'sorl.thumbnail',
 'constance',
 'constance.backends.database',
 'djmail',
 'bootstrap_pagination')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.contrib.admindocs.middleware.XViewMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'wagtail.wagtailcore.middleware.SiteMiddleware',
 'wagtail.wagtailredirects.middleware.RedirectMiddleware')


Traceback:  

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  42.             response = get_response(request)

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  217.                 response = self.process_exception_by_middleware(e, request)

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  215.                 response = response.render()

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/template/response.py" in render
  109.             self.content = self.rendered_content

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/template/response.py" in rendered_content
  86.         content = template.render(context, self._request)

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/django/template/base.py" in render
  206.                 with context.bind_template(self):

File "/usr/lib/python3.5/contextlib.py" in __enter__
  59.             return next(self.gen)

File "/home/rolc/.virtualenvs/dev/lib/python3.5/site-packages/debug_toolbar/panels/templates/panel.py" in _request_context_bind_template
  49.         context = processor(self.request)

File "/home/rolc/dev/royal_orchard/blog/context_processors.py" in context
  10.     user = request.user

Exception Type: AttributeError at /cms/pages/29/edit/preview/
Exception Value: 'WSGIRequest' object has no attribute 'user'
Request information:
USER: Robert ***********

GET: No GET data

POST:
seo_title = ''
expire_at = ''
csrfmiddlewaretoken = '******'
body-0-type = 'paragraph'
body-count = '1'
go_live_at = ''
body-0-deleted = ''
search_description = ''
body-0-order = '0'
slug = '******-history'
title = '****** History'
next = ''
body-0-value = '<p>I feel so very privileged to be invited into your home and if we also feel a little intimidated because we are talking to folks who have generational knowledge of this wonderful house and I know as we do so we are little bit nervous about giving you advice on wh</p>'
  • Python version: 3.5.2.
  • Django version: 1.10.6.
  • Wagtail version: 1.9.
  • Browser version: Firefox 52.0.2 on Ubuntu Linux.
  • Gunicorn: 19.7.1
  • Nginx: 1.10.0

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:1
  • Comments:25 (12 by maintainers)

github_iconTop GitHub Comments

5reactions
emorozovcommented, Apr 22, 2017

@gasman Thank you! Your suggestion was right. I’ve found the problem: Wagtail uses its own Site model which is set to localhost by default. Since, on staging/production sites there’s no localhost in settings.ALLOWED_HOSTS, CommonMiddleware was failing and exception message was silently suppressed. So, no session and authentication middleware were run, but exception was lost somewhere, so it was almost impossible to find the real cause of the problem.

I think this is still a bug. It should be either documented somewhere to set proper hostname for the wagtail Site (can it take value from Django Site which is properly set to staging hostname?) or the real exception should be displayed to the user, not silently ignored.

3reactions
gasmancommented, Jul 11, 2019

See #5427 for a full diagnosis and (hopefully) fix.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Deploy Python WSGI Apps Using Gunicorn HTTP ...
We will begin with expanding our knowledge on the excellent Gunicorn WSGI HTTP Server and continue with deploying Python WSGI web ...
Read more >
Running Gunicorn — Gunicorn 20.1.0 documentation
You can run Gunicorn by using commands or integrate with popular frameworks like Django, Pyramid, or TurboGears. For deploying Gunicorn in production see ......
Read more >
Django Deployment on App Service Linux -
remote: Triggering recycle (preview mode disabled). remote: Deployment successful. By default when deploying a Django application with Python on ...
Read more >
Python and Django tutorial in Visual Studio Code
The wsgi.py and asgi.py modules in the Django project take care of hooking into the ... In other words, if the debugger doesn't...
Read more >
How to Code with Me - Wrapping a Flask App in a CLI
wsgi located at src/granola_explosion/wsgi.py . This tutorial isn't about building a Flask application, so below I'll give a minimum working ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found