Preview mode doesn't work under WSGI/Gunicorn
See original GitHub issueIssue Summary
Attempt to preview any page results in exception.
Steps to Reproduce
- Open any page in the WagTail CMS for editing
- 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:
- Created 6 years ago
- Reactions:1
- Comments:25 (12 by maintainers)
Top GitHub Comments
@gasman Thank you! Your suggestion was right. I’ve found the problem: Wagtail uses its own
Site
model which is set tolocalhost
by default. Since, on staging/production sites there’s no localhost insettings.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 DjangoSite
which is properly set to staging hostname?) or the real exception should be displayed to the user, not silently ignored.See #5427 for a full diagnosis and (hopefully) fix.