Skip to content
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

Preview mode doesn't work under WSGI/Gunicorn #3546

Open
emorozov opened this issue Apr 14, 2017 · 28 comments
Open

Preview mode doesn't work under WSGI/Gunicorn #3546

emorozov opened this issue Apr 14, 2017 · 28 comments
Labels
component:Preview Page lives preview functionality, viewing drafts type:Bug
Milestone

Comments

@emorozov
Copy link
Contributor

emorozov commented Apr 14, 2017

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
@emorozov emorozov changed the title Preview mode doesn't work under WSGI Preview mode doesn't work under WSGI/Gunicorn Apr 14, 2017
@alexfromvl
Copy link
Contributor

I use the wagtail 1.9 on the site together with the Gunicorn. The preview_mode works well.

Probably you have a problem in the settings of the Gunicorn or Nginx.

@emorozov
Copy link
Contributor Author

emorozov commented Apr 20, 2017

There's nothing unusual in my configuration.
Gunicorn is started with this cmdline:
/home/rolc/.virtualenvs/dev/bin/gunicorn --pid /run/gunicorn-dev/pid -b unix:/run/gunicorn-dev/socket --reload app.wsgi:application

Nginx conf is:

    location / {
        expires -1;

        proxy_read_timeout 1200;
        proxy_send_timeout 1200;
        proxy_connect_timeout 1200;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-SSL on;
        proxy_redirect off;

        if (!-f $request_filename) {
            proxy_pass http://unix:/run/gunicorn-dev/socket;
        }
    }

No other piece of code or third-party app fails under this configuration, only Wagtail preview. :(

@alexfromvl
Copy link
Contributor

You need to look at the mistakes associated with Django. Because the error is in the user "'WSGIRequest' object has no attribute 'user'"

https://docs.djangoproject.com/en/dev/ref/middleware/#django.contrib.auth.middleware.SessionAuthenticationMiddleware

@gasman
Copy link
Collaborator

gasman commented Apr 20, 2017

Looking closely at the stack trace here, I think there might be a different exception being thrown during middleware processing (probably because the dummy request is missing some other property that the middleware depends on) - as a result, it never reaches AuthenticationMiddleware, and it's failing with 'WSGIRequest' object has no attribute 'user' while attempting to render the error page.

Please can you try updating blog/context_processors.py so that it doesn't fail in the absence of request.user, and see if that gives a more helpful error?

@emorozov
Copy link
Contributor Author

emorozov commented Apr 20, 2017

When I modify the context processor to not fail in absence of request.user, preview doesn't fail. It seems that AuthenticationMiddleware unable to load user when it's using fake request.

It seems that AuthenticationMiddleware isn't even called. I've added debug print to the AuthenticationMiddleware but it is never called when there's an error.

@emorozov
Copy link
Contributor Author

I have added debug prints to wagtail and django and here's what I get:

Procesing request <WSGIRequest: GET '/cms/pages/29/revisions/4/view/'> with middleware <django.middleware.security.SecurityMiddleware object at 0x7fa625f1cf98>
Procesed
Procesing request <WSGIRequest: GET '/cms/pages/29/revisions/4/view/'> with middleware <django.contrib.sessions.middleware.SessionMiddleware object at 0x7fa625f1cf60>
Procesed
Procesing request <WSGIRequest: GET '/cms/pages/29/revisions/4/view/'> with middleware <django.middleware.common.CommonMiddleware object at 0x7fa625f1cb70>
Procesed
Procesing request <WSGIRequest: GET '/cms/pages/29/revisions/4/view/'> with middleware <django.contrib.auth.middleware.AuthenticationMiddleware object at 0x7fa625f1c7b8>
Procesed
Procesing request <WSGIRequest: GET '/cms/pages/29/revisions/4/view/'> with middleware <django.contrib.messages.middleware.MessageMiddleware object at 0x7fa625f1c7f0>
Procesed
Procesing request <WSGIRequest: GET '/cms/pages/29/revisions/4/view/'> with middleware <wagtail.wagtailcore.middleware.SiteMiddleware object at 0x7fa626030780>
Procesed
starting processing request <WSGIRequest: GET '/pages/info/milner-history/'>
Procesing request <WSGIRequest: GET '/pages/info/milner-history/'> with middleware <django.middleware.security.SecurityMiddleware object at 0x7fa622b92908>
Procesed
Procesing request <WSGIRequest: GET '/pages/info/milner-history/'> with middleware <django.contrib.sessions.middleware.SessionMiddleware object at 0x7fa622b92898>
Procesed
Procesing request <WSGIRequest: GET '/pages/info/milner-history/'> with middleware <django.middleware.common.CommonMiddleware object at 0x7fa622b92b00>
finished processing request <WSGIRequest: GET '/pages/info/milner-history/'>

So it seems, that all middleware is applied to the original request, but only first three entries are applied to the dummy request for some reason. There're no errors during middleware loading and application, so I still can't find the reason why AuthenticationMiddleware is never called for dummy request.

@gasman
Copy link
Collaborator

gasman commented Apr 21, 2017

@emorozov Is it possible that CommonMiddleware is returning a (non-error) response? In this situation the rest of the middleware chain is skipped. (For old-style MIDDLEWARE_CLASSES definitions, we explicitly ignored those responses and continued with the chain. Perhaps we need to do that with new-style middlewares too...)

@emorozov
Copy link
Contributor Author

emorozov commented 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.

@BenSturmfels
Copy link
Contributor

BenSturmfels commented Jun 19, 2017

I've been able to get the preview working under Django 1.8, but not under 1.10, using the same settings (aside from rename of MIDDLEWARE/MIDDLEWARE_CLASSES). Haven't had a chance to investigate.

@BenSturmfels
Copy link
Contributor

Hi @emorozov, sorry to be a pain, but could you please add some details about closing this issue?

@SalahAdDin
Copy link
Contributor

@emorozov, i want to know the same.

@emorozov
Copy link
Contributor Author

@BenSturmfels @SalahAdDin The problem only occurs when wagtail site hostname mismatches the real hostname. You need to check if you have the site hostname set correctly in the Django admin.

@BenSturmfels
Copy link
Contributor

@emorozov glad you were able to resolve your issue, but if configuring the hostname incorrectly results in the somewhat baffling 'WSGIRequest' object has no attribute 'user', I think we need a better solution. Otherwise this is going to cause a headache for a lot of people unnecessarily.

@emorozov
Copy link
Contributor Author

@BenSturmfels then the proper solution would be one of the following:

  • ignore middleware errors during processing dummy wagtail request
  • remove common middleware from the list of middleware when processing dummy request
  • do not use middleware at all when processing fake request

Like I said in the initial message this whole dummy request thing for preview feels like a crutch. I have a feeling that it can be made in a more robust and elegant manner, but I'm not really sure I can do it.

@gasman
Copy link
Collaborator

gasman commented Jul 27, 2017

Reopening this, since the current behaviour is a regression from the pre-Django-1.10 middleware where we ignored any responses (error or otherwise) originating from middleware. I'm not sure of the best way to fix it, though...

ignore middleware errors during processing dummy wagtail request

I can't see a good way to do that with Django's current middleware implementation - in the old-style middleware, we called process_request on each middleware class in turn, so we knew when a middleware was returning its own response. In the new style, the outer classes completely wrap the inner ones, so there's no way to tell from outside whether the response originates from the middleware or the actual view.

remove common middleware from the list of middleware when processing dummy request

This might work, but it feels like a "band-aid" fix - it's possible that other middlewares will have similar issues. (In fact, I'm not sure that CommonMiddleware is the culprit here - checking ALLOWED_HOSTS seems to happen in the Request object itself, so it could occur in any place that tries to retrieve hostname.)

do not use middleware at all when processing fake request

This isn't an option - the page template will often rely on variables that are inserted in middleware, such as request.user or request.site. For similar reasons I don't think we can avoid the dummy_request mechanism - the template author should be free to use any properties of the request object, so it's Wagtail's responsibility to make sure that the request object is as close as possible to the one that would be seen on a real page request.

One possibility is to add a system check that generates a warning on startup if any Site records have hostnames that aren't covered by ALLOWED_HOSTS. However, one goal I've always had with the design of Wagtail is that Site records should just work out of the box for single-site installations, and you shouldn't have to care about configuring them until you come to build a multi-site project. (For example, that's why Page.get_url() returns a local URL without the hostname on single-site installations). So maybe it's better to pre-emptively check ALLOWED_HOSTS in dummy_request, and silently fix up the host header if we can see it's going to break...

Incidentally, the unhelpfulness of the 'WSGIRequest' object has no attribute 'user' error is not Wagtail's fault - it's because you have code in context_processors.py that's not robust enough against error conditions (i.e. it's expecting to find attributes of request that aren't guaranteed to be there).

@abadger1406
Copy link

abadger1406 commented Sep 20, 2018

'WSGIRequest' object has no attribute 'user'

This error seen after upgraded site and try to view a form in preview mode...

(nw) dave@big5:/home/nw/nw/settings$ pip freeze
beautifulsoup4==4.6.0
certifi==2018.8.24
chardet==3.0.4
Django==2.0.8
django-debug-toolbar==1.10.1
django-extensions==2.1.2
django-modelcluster==4.2
django-taggit==0.23.0
django-treebeard==4.3
djangorestframework==3.8.2
draftjs-exporter==2.1.2
html5lib==1.0.1
idna==2.7
Pillow==5.2.0
pkg-resources==0.0.0
pytz==2018.5
requests==2.19.1
six==1.11.0
sqlparse==0.2.4
Unidecode==1.0.22
urllib3==1.23
uWSGI==2.0.17.1
wagtail==2.2.2
webencodings==0.5.1
Willow==1.1

screenshot from 2018-09-20 14-20-07

@abadger1406
Copy link

abadger1406 commented Sep 20, 2018

If helpful...

(nw) dave@big5:/home/nw$ tail -f logs/uwsgi.log
File "/home/Env/nw/lib/python3.6/site-packages/wagtail/core/models.py", line 1324, in serve_preview
return self.serve(request)
File "/home/Env/nw/lib/python3.6/site-packages/wagtail/contrib/forms/models.py", line 237, in serve
form = self.get_form(page=self, user=request.user)
AttributeError: 'WSGIRequest' object has no attribute 'user'

@gasman
Copy link
Collaborator

gasman commented Sep 20, 2018

@abadger1406 That one's a bit puzzling - request.user would be missing if something failed during the middleware stage, but in that case I can't see how it would proceed to the form page model's serve method. Can you post the complete traceback, please?

@jayden2
Copy link

jayden2 commented Oct 1, 2018

After upgrading to 2.2.2 from 2.0 I have noticed this on production only:

AttributeError
'WSGIRequest' object has no attribute 'site'

An odd thing I've also noticed is if I change the sites port to say 200, and then refresh the preview page the page loads. Then on subsequent loads the above error happens.

@Chukwunonso
Copy link

Had this problem while upgrading to Django 2.1.7 and Wagtail 2.4 from 1.10.3 and 1.13 respectively.
Seemed none of the middleware was being triggered including the wagtail.core.middleware.SiteMiddleware which should set the site attribute to the request object. The issue went away when I changed the middleware setting from

MIDDLEWARE_CLASSES = (...)

to

MIDDLEWARE = (...)

gasman added a commit to gasman/wagtail that referenced this issue Jul 10, 2019
Django-1.10-style middleware inherently doesn't support applying middleware to the request independently of running the view function, as the design of dummy_request requires. The current implementation of dummy_request unwittingly works around this by running the entire request/response cycle on the page's live URL (regardless of whether the page actually exists there at that moment), throwing away the response, and returning the request object to be used a second time (at which point it will be hopefully be populated with middleware-supplied attributes such as request.user and request.site - unless something caused the middleware to abort).

The new make_preview_request method wraps the call to serve_preview inside the middleware processing, so there is no longer a bogus 'background' request and no response has to be thrown away (meaning that any response returned by middleware will be correctly returned).

Fixes wagtail#3546
@gasman
Copy link
Collaborator

gasman commented Jul 11, 2019

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

@gasman gasman closed this as completed in e400d8d Aug 8, 2019
huynhsontung added a commit to wethegit/wagtail that referenced this issue Apr 22, 2020
* Adds Collections section to editor's guide

* Add form media to users/edit.html (wagtail#5390)

* Adds screen-reader-only text to the close button for modals (wagtail#5274, wagtail#5377)

* Adds clearer text to the close button for modals
* Use existing wagtailConfig.STRINGS to store the new translatable string for JS, rather than introducing a new library.
* Update list of string constants for translation in the tests file
* Remove aria-hidden on modal dialog close button

* Ensure the 'add child page' button displays when focused (wagtail#5274, wagtail#5382)

* Fix elasticsearch search backend tests broken by wagtail#5208

* Remove buggy tab order customisations in CMS admin (wagtail#5383, wagtail#5351)

* Fix spelling (wagtail#5393)

* Add labels to permission checkboxes for screen reader users (wagtail#5329, wagtail#5395)

- adds a fieldset around checkboxes with the same name
- add correct labels for object permissions table
- Ensure that image and document permissions labels display correctly, and ensure that labels for the dropdowns for document and image collections are not display:none
- Hide labels from sighted users in group edit / group add pages

* Optimization of UserPagePermissionsProxy.revisions_for_moderation (wagtail#5311)

revisions_for_moderation() was iterating over Page instances only
to use their path attribute. The optimization uses values_list()
over the GroupPagePermission queryset to retrieve only the page
paths without having to create the model instances in memory. This
saves roughly 50% of the runtime.

* Re-add loading of Wagtail icon font for userbar. Fix wagtail#5397 (wagtail#5398)

* Refactor submenu JS to remove jquery dep and move to wagtail-client (wagtail#5254)

* Add more contextual information for screen readers in the explorer menu’s links (wagtail#5335, wagtail#5386)

* Add dedicated accessibility section to v2.6 release notes (wagtail#5402)

* Add process_child_object method to Page.copy

* Add "exclude_fields" parameter to Page.copy

Also, make the excluded fields take effect on child relations as well

* Provide the original and copied pages to process_child_object()

* Add tests for Page.copy() process_child_object and exclude_fields

* Release notes for wagtail#5183

* Implement Page.with_content_json and add to docs (fixes wagtail#5199)

* Tests for wagtail#5203

* Release notes for wagtail#5203

* Improve screen-reader labels for action links in page listing (wagtail#5274, wagtail#5380)

* Move focus to the pages explorer menu when open (wagtail#5336, wagtail#5394)

* Ensure that when you open the explorer the focus moves to the first link of the menu, and add a label for the explorer navigation
* Add dialog role to pages explorer popup, and ensure that there is an option to close the dialog window when tabbing by making the close button visually hidden rather than display none

* Added CI config to generate nightly builds from master (wagtail#5320)

* Added CI config to generate nightly builds from master

* Fix typo

* Don't write __init__.py directly

We need to import the original in the script

* Update wagtail.utils.version

This is based off a copy from Django master made just now and adds
support for 'dev' versions.

* Try pip install --user

* Add screen-reader labels across multiple parts of the UI (wagtail#5274, wagtail#5339, wagtail#5372)

* Rename _utilities.hidden.legacy.scss to _utilities.visuallyhidden.scss (wagtail#5404)

We will always need visuallyhidden styles for screen readers.

* Update CONTRIBUTORS.rst

* added construction_hook_name to settings_menu (wagtail#5384)

* Clarify new three month release policy

* Adjust link label

* Update third_party_tutorials.rst

Add a detailed article about using GraphQL in Wagtail

* Nightly: Upload builds to 'dist' subfolder

* Nightly: Upload builds to 'dist' subfolder

* Nightly: Keep latest.json public when updating

* Nightly: Add script for testing nightly builds

* Document the workaround for broken wagtailimages.Filter references in custom image migrations

* Added missing is_stored_locally() to AbstractDocument

* Datetime picker dispatches 'change' event

* Also add change event to timepicker and datepicker

* Search query normalisation no longer removes punctuation wagtail#5416

* Don't make assumptions about the username field

The USERNAME_FIELD exists to allow customisation. Therefore we should make an assumption that `.username` exists on the model. Instead, we need to pull the required value from the USERNAME_FIELD and add in a fallback default.

* Optimize admin.navigation.get_explorable_root_page

Testing the queryset in the if clause was causing the whole queryset
to be retrieved and populated from DB, all to check whether it was empty
or not.

The optimization is to rely on the strict behavior of
first_common_ancestor, which raises an exception if the queryset is
empty.

* Fetch new translations from Transifex

* Generate new strings for translation

* Version bump to start work on 2.7

* Add 2.7 section to changelog and release notes

* Fix update docs typo

Only two Ss in accessor. Also make quotes consistent.

* Remove features deprecated in 2.7

* Rotate deprecation warnings for 2.7

* Pin Squash docker image to a specific version (wagtail#5441)

Recent builds have been breaking due to the following error: `/post_build.sh: line 2: npm: command not found`. I’m not entirely sure this is the fix, but it looks like this `latest` tag is now resolving to `3.7.4-buster` (https://hub.docker.com/_/python). Debian Buster got released 2 weeks ago. It feels safer to have a pinned dependency, and Stretch is probably what it was resolving to before.

* Add a `construct_page_listing_buttons` hook

This hook mimics the functiolity provided by `construct_page_action_menu`
in that it constructs the final list of buttons to be shown in the wagtail
admin interface.  This means that within this function button's can be
removed, added or re-ordered.

See wagtail#4925

* Updated feature detection notes

* Fix broken pipenv/docutils dependency on CircleCI

* Break long file titles on multi file upload listing

* Fix docs title to break for long filenames

* Release note for wagtail#5431

* Add https support for scribd oembed provider (wagtail#739)

Currently scribd defaults to https for their sharing links - http still works but if you copy&paste quickly you may think it's broken

* Fix the required styles on title fields (wagtail#5440)

* Change StreamField group labels color so labels are visible. Fix wagtail#5455 (wagtail#5462)

* use lighter grey for streamfield group label for accessible contrast

* Fix jcrop holder image having no alt tag

* Pass down process_child_object when copying recursively

* Delay dirty form check data snapshot to avoid race conditions. Fix wagtail#4978 (wagtail#5469)

User interaction with the form within the 10s delay also won’t trigger the confirmation message. There will still be race condition issues if form widgets like rich text take 10+ seconds to initialise – but that doesn’t seem likely.

* Add release notes for 2.5.2

* Fetch new translations from Transifex

* Fill in release date for 2.5.2

* Fill in release date for 2.6

* Make image fallback work for images with big/small aspect ratios. Fix wagtail#5472 (wagtail#5474)

* Add support for phone links in rich text

This is mainly copy paste of Liam Brenner work (wagtail#3776) but with
a few fixes to make it work with Draftail. Since mailto:-links
is supported i think it is reasonable to support tel:-links as
well

* Apply escaping to JS translation strings. Fixes wagtail#5477

* Add release notes for 2.6.1

* Prevent exception when attempting to delete a model with a protected 1-to-1 relation

Modeladmin handles notification to the user if a model instance has protected ForeignKey
relationships. However, if the protected relation is a OneToOneField it raises an exception:

  File ".../wagtail/wagtail/contrib/modeladmin/views.py", line 742, in post
    for obj in qs.all():
AttributeError: 'MyRelatedModel' object has no attribute 'all'

because qs in this case is the related instance rather than a queryset of related instances
(as is the case for a ForeignKey).

This commit handles the OneToOneField case as well.

* Move and refactor upgrade notification JS

* Clarify CHANGELOG instructions in "Committing code" docs (wagtail#5483)

* Fill in release date for 2.6.1

* Add labels to snippet bulk edit checkboxes for screen reader users. Fix wagtail#5328 (wagtail#5463)

* Resolve DeprecationWarning (wagtail#5485)

Resolves "DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working" - see wagtail#5484

* Use xenial for all travis builds

* Test against Python 3.8 dev build

* Add (failing) test for middleware responses during preview

Responses returned by middleware (e.g. authentication failure) while creating the dummy request for a page preview. However, the current (broken) behaviour is to ignore the response, and attempt to serve the preview using the resulting request - which is likely to have incompletely-applied middleware, leading to hard-to-debug issues (usually involving a missing request.site).

* Introduce make_preview_request method to supersede dummy_request

Django-1.10-style middleware inherently doesn't support applying middleware to the request independently of running the view function, as the design of dummy_request requires. The current implementation of dummy_request unwittingly works around this by running the entire request/response cycle on the page's live URL (regardless of whether the page actually exists there at that moment), throwing away the response, and returning the request object to be used a second time (at which point it will be hopefully be populated with middleware-supplied attributes such as request.user and request.site - unless something caused the middleware to abort).

The new make_preview_request method wraps the call to serve_preview inside the middleware processing, so there is no longer a bogus 'background' request and no response has to be thrown away (meaning that any response returned by middleware will be correctly returned).

Fixes wagtail#3546

* Update dummy_request tests to use make_preview_request

* Deprecation note for dummy_request

* Release note for wagtail#5427

* Don't use page admin title when editing rich text (wagtail#5491)

When editing a rich text field and entering a link to a page whose Page
type overrides get_admin_display_title, the custom admin display title
is used both when browsing to select the page to link to and also when
viewing the rich text editor.

The first behavior is consistent with how custom admin display titles
are used throughout the admin, but the second behavior is not. The
Wagtail user should be able to use the rich text field as a reasonable
preview of what the rendered content will look like for the end user. To
do this, the "real" page title should be used, not the admin one.

This commit alters the data that gets passed to the rich text editor so
that its title is the real page title and not the admin one.

Fixes issue 5131.

* Properly check permissions when viewing revisions (wagtail#5490)

Currently any user with any page permission can view any page revision.
This commit fixes that, and ensures that the user has publish or edit
permission on the page before showing a page revision. If not, the user
is presented with a 403.

This maintains the current behavior if the user has no page permissions,
which is to redirect to the admin home page.

New tests have been added to cover these changes.

Fixes issue 5426.

* Fix pageurl and slugurl handling of situations where request.site is null (wagtail#5501)

* Add caption field to TableBlock

* Create caption field added to table block widget

Caption allows for users users with screen readers to be
able to understand the contents of a table.

* Fixed bugs in javascript and typos

* Updated documentation and change log

* Fixed table caption bug and requested pr edits

* Fixed table caption bug and request pr edits

* Removed changes in changelog.txt

* Fixed bug and requested PR edits

* Output form media on add/edit/chooser image forms with custom models

* Add tests for custom image on multiple image uploader
* Output form media on image add/edit views
* Output form media for 'add image' form within image chooser modal
Note: this won't work reliably if the media is hosted on a CDN, because script tags inserted as part of a jQuery DOM insertion (as modals are) are loaded asynchronously and not guaranteed to complete loading before inline scripts are run. It's better than not having the includes there at all though...

* Upgrade minimum 6.x release for Elasticsearch to 6.4.0

Fix doc and test on ES6 python client compat

This commit changes the statement that version < 6.3.1 of the
elasticsearch python client should be used to instead state
that 6.4.0 is fine.

It also update the tests to reflect the statement.

Initially the `update_all_types` argument has been used to work
around an issue described in:
wagtail#2968

This argument was removed in elasticsearch-py 6.3.1 and making
use of it was raising an error.

With 6.4.0 nothing is raising anymore.

* Add ability to create anchor link tab within rich text link

- add tests

- Update changelog & release notes

* Update Changelog

* Upgrade django-taggit to 1.x

django-taggit 1.x drops Python 2.x support and thus the dependency on django.utils.six; this is a prerequisite for supporting Django 3.0.
The signature of TaggableManager.value_from_object has changed to return a list of Tags (previously it was a QuerySet of TaggedItems) and so search indexing and comparison need to be updated accordingly. There is a corresponding fix to ClusterTaggableManager in django-modelcluster 5.0.

* Fix failing tests due to different HTML escaping in Django 3.0

- Fix password reset tests
- Fix test for invalid-slug message
- Update changelog/release notes

* Fixes layout for the FileField

* Allow users to change their first and last name

* Move locale-related functions from wagtail.admin.utils to wagtail.admin.locale

* Move model-related functions from wagtail.admin.utils to wagtail.admin.models

* Move authentication-related functions from wagtail.admin.utils to wagtail.admin.auth

* Move authentication-related functions from wagtail.admin.decorators to wagtail.admin.auth

* Move email functions from wagtail.admin.utils to wagtail.admin.mail

* Move get_site_for_user to wagtail.admin.navigation

* Update docs with new locations of wagtail.admin.utils definitions

* Fix MovedDefinitionHandler deprecation warnings to point to the import location

* Update wagtail.admin.utils and wagtail.admin.decorators imports to new locations. Fixes wagtail#5507

* Make try/catch AttributeError less all-encompassing

* Update references to wagtailadmin in comment

* Fix mention of non-existing PageLinkHandler.get_identifier

Refs wagtail#5184

* fix(docs/customization): Add models import to fix example (wagtail#5520)

* Remove Unidecode from postgres_search. Fix wagtail#5001 (wagtail#5514)

* Updated contributors & changelog

* Add telephone number links to release notes

* Replace streamfield CSS with react-streamfield CSS

* Update list / struct / stream block markup to match react-streamfield CSS

* Fix streamfield tests for updated markup

* Updates broken JS tests.

* Updates to react-streamfield 0.9.5.

* Release note for StreamField design update (wagtail#5476)

* Update release schedule info and move dates table to the wiki

Document release schedule in readme

* update docs for TabbedInterface (wagtail#5374)

* Allow content to define the tab width on xs screens to stop cutting off text (wagtail#5392)

* Break listing titles by word so action buttons are visible on smaller screens (wagtail#5429)

* Changed Snippet Chooser AJAX delay from 50ms to 200ms, to remove laggy typing. (wagtail#5439)

50ms is the equivalent of about 200 words per minute, so typing slower than that
meant that the javascript would send an AJAX request between every single
keystroke. This change makes the javascript wait for 200ms between keystrokes,
which lets you finish typing the word you're looking for before it sends an AJAX
request.

* Update CONTRIBUTORS.rst

Correction to contributor's name per request by email

* Add wagtail nightly to readme

* Add note about CurrentSiteMiddleware incompatibility

As per wagtail#2840 (comment)

* fix: Language chosen in user preferences persists on subsequent requests (wagtail#4310)

* Add SECURITY.md (wagtail#5536)

Adds security.md to be consistent with github's interface

* Fix compatibility with pylint-django (wagtail#5538)

It's not possible to use wagtail in a project with pylint and the
pylint-django plugin.

Pylint-django does not work with foreign keys that are referenced by
their string names. See: https://github.com/PyCQA/pylint-django#known-issues

If we simply replace the string name with the foreign-key class, linting
on wagtail projects is fixed.

Also see:
pylint-dev/pylint#2995
pylint-dev/pylint-django#241

* Add setting to disable email management

This commit adds WAGTAIL_EMAIL_MANAGEMENT_ENABLED setting that defaults
to True, but when disabled, hides the 'Change email' button in account
management view, and disables the associated route. This is useful when
using external authentication method like LDAP or OpenID Connect where
email management is handled elsewhere.

Wagtail already includes WAGTAIL_PASSWORD_MANAGEMENT_ENABLED setting.
This is almost exact copy of that implementation.

* Replaced SafeText with SafeString.

* Replaced use of force_text with force_str.

* Updated the block id initialization (wagtail#5552)

The current block id generation only sets the id as the block is serialized for storage in the database, which means that the id is unavailable in the block until it is pulled back from the database. In my debugging this caused the id to be set to new values up to 3 times when saving a brand new page (each time with a new id).
This updated logic applies the new id to the actual block which makes it available right away and prevents the id from being regenerated.

* Stopped inheriting from object.

* Fixed broken email header when hosting static files remotely (wagtail#5543)

Fixes wagtail#5525

* Split up wagtail.admin.tests.test_pages_views

* Fix Postgres search indexing on Postgres 9.4 and Django >=2.2.1

Fixes wagtail#5547
As of Django 2.2.1, Value expressions within a SearchVector must specify an output_field: https://code.djangoproject.com/ticket/30446

* Release note for wagtail#5559

* Fix soundcloud embed regex

* Update core team list in CONTRIBUTORS.rst

* Fill in release date for 2.6.2

* Fetch new translations from Transifex

* Add translator credits

* Add core team alumni section to contributors

* Marks preview models for translation

* Fix class selector mapping (wagtail#5571)

The markup is wrong which results in code not working properly.

* add WAGTAILDOCS_SERVE_METHOD setting to allow serving files from underlying storage

* Documentation tweaks for WAGTAILDOCS_SERVE_METHOD

As suggested by @chosak - wagtail#5296 (comment) , wagtail#5296 (comment)

* Additional tests for document.url and serve view behaviour

* Release note for wagtail#5296

* Update configuration.rst (wagtail#5576)

* Add ability to hide 'Submit for Moderation' in action menu using setting WAGTAIL_MODERATION_ENABLED. When set to false, SubmitForModerationMenuItem method is_shown returns false (wagtail#5574)

* allow image page sizes to be configurable (wagtail#5568)

* Updating FieldDoesNotExist imports to all be django.core.exceptions. (wagtail#5581)

* Test Django master against django-modelcluster master

* Eliminate dependency on default User model from style guide

Fixes wagtail#5442. Building a User object for [email protected] may cause problems if a custom user model is in use, and is redundant anyhow because there's no longer a registered gravatar for that email - we should just hard-code the default blank avatar instead.

* Update more FieldDoesNotExist imports as per wagtail#5581

* Add role="table" to TableBlock output

As per https://twitter.com/SaraSoueidan/status/1177622630763028480, certain browsers apply heuristics to decide whether `<table>` elements exist for layout or data purposes, and adjust the behaviour of their accessibility features accordingly. Given that TableBlock intentionally doesn't allow markup within cells, we can be reasonably sure that any tables created with it are genuine data tables, and should therefore indicate that using `role="table"`.

* Make DraftailRichTextArea be considered as visible (wagtail#5583)

* Make it possible to override the url used by Page._get_dummy_headers()

* Changed height's description to match  width's. (wagtail#5593)

* Add a note on 'Previewing and Submitting for Moderation' page about potential disabled moderation

* Add new docs page 'Changing rich text representation' (wagtail#5579)

* Add new docs page 'Changing rich text representation' describing how to subclass Format to provide a custom image html representation in rich text

* Output form media on add/edit/chooser document forms with custom models

Similar to eaad013, but for Document

* Deduplicate creation of fake file in document tests

* Add separate GitHub issue templates for feature requests and bugs. Fix wagtail#5560 (wagtail#5594)

* Add cache-busting parameter to admin static files

Fixes wagtail#5493

* Disable querystrings if a storage backend with hashed filenames is active

* Added upgrade note about disabling version strings

* Release note for wagtail#5527

* Implements ES7 support (wagtail#5611)

* Implements ES7 support

* Linter fix

* Adds docs

* isort fix

* Fixes typo

* Release notes for wagtail#5611

* Allow default item in action menu to be overridden with construct_page_action_menu hook

Fixes wagtail#5438

* Add 'Page locked' as a distinct menu item

* Revise action menu ordering so that the first (not last) item is picked as the default

Addresses backwards compatibility of existing action menu hooks, as per wagtail#5500 (review)

* Update construct_page_action_menu example

Now avoids redefining the whole list, and reflects the fact that the first (rather than last) item is picked as the default.

* Add release note about template change for action menu items

* Clarify that menu item order attribute is ignored in construct_page_action_menu

* Release note for wagtail#5500 / wagtail#5612

* Add acknowledgement to The Motley Fool

* Remove mentions of Django 3.0 compatibility from release notes

Work on compatibility is ongoing while Django 3.0 is still in development; we don't want this to be misinterpreted as a statement of formal Django 3.0 support (which we can't promise until the final release)

* Add example of template rendering to TableBlock docs

Addresses wagtail#5540

* Added 'image uploads in forms' to third party tutorials

* Fix multiple minor documentation issues

- Typo in readme (verb did not agree with the subject)
- Grammatical error in topics/pages
- wagtail#5364 - Update URL config code block in getting-started/integrating-into-django

* Replace format() placeholders in translatable strings with % formatting

Fixes wagtail#5539. Transifex and Django's makemessages command have validation to catch invalid placeholder variables within translated strings - for example, where the translator has translated the variable name - but these only recognise old-style `%` formatting, not the `format` method, and so it's better for us to standardise on % formatting.

To reduce the burden on translators having to re-translate these strings, only the ones using named placeholders (`"Edited page {title}"`) rather than numeric ones (`"Edited page {0}"`) have been changed - hopefully the latter give less room for error.

Also fixed some incorrect use of plurals (verbose_name vs verbose_name_plural) in snippet confirmation messages.

* Docs - Add AbstractUser import to custom user model

- `from django.contrib.auth.models import AbstractUser`
- revise a previous changelog entry to clarify 'clean up' vs 'fix'

* Recommend signals rather than hooks for model-level customisations

As per wagtail#5620 - signals are often overlooked as a way of customising model-level behaviour. We should recommend them over admin hooks where possible, as they aren't reliant on users taking one particular path through the admin - for example, an 'add document' signal will be triggered regardless of whether a document is created through the single uploader, multiple uploader, chooser model or a scripted task, whereas a hook would not catch all of these cases.

* Formalise Python 3.8 support

* Make copy of ES6 settings before setting max_ngram_diff (wagtail#5625)

* Change string based reference to class based

* Add model to PersonAdmin in documentation

* Replace rawgit.com links with jsdelivr

rawgit will be shut down soon

* Add thanks to squash.io

* [5225] Take number of frames into account when limiting image size

* Revert "Formalise Python 3.8 support"

This reverts commit ddbbaea.

* Add webp support

* Support format-webp and allow changing default formatting

* Add tests for webp format conversion

* Release note for wagtail#5249 / wagtail#5629

* Add documentation for how to use alternative image tags

This adds documentation for alternative image tags such as `<picture>`
and `<amp-img>`.

* Improvements to "Alternative HTML tags" based on review feedback

* syntax => keyword

* Rename wagtail/admin/locale.py to localization.py

Having a module called locale interferes with Django's makemessages / compilemessages commands :-(

* Changelog cleanup

* note Python 3.8 support as provisional
* Remove mentions of minor doc fixes (there are many more fixes beyond the ones mentioned here, and including them all in the release notes would add too much noise...)

* Fetch new translations from transifex

* Remove redundant ugettext_lazy from non-text labels

* Generate new strings for translation

* Version bump to 2.7rc1

* Ensure admin API always uses SessionAuthentication backend

Fixes wagtail#5585 and (at least partly) wagtail#5628

* Release note for wagtail#5643 in 2.6.3

* Release note for wagtail#5643 in 2.7

* Version bump to 2.7rc2

* Formalise Python 3.8 support

* Mark Python 3.8 support as official in changelog

* Avoid calling versioned_static from static form media definitions (wagtail#5644)

* Avoid calling versioned_static from static form media definitions

Fixes wagtail#5632

Defining media definitions with `class Media:` means that those lines are evaluated on application startup; this means that they cannot contain calls to the Django static file finder, because ManifestStaticFilesStorage doesn't work until collectstatic has completed. Fix this by making those definitions into `def media(self):` methods.

* Add test to confirm that inheritance still works with dynamic form media definitions

* Fetch new translations from Transifex

* Fixed 2.6.3 date in Changelog and updated username on Contributors

* Added label 'URL' for external link

- Regression - missing label for external link URL field in link chooser
- Resolves wagtail#5656

* Fix contributor name

- incorrectly added the issue creator not the PR creator
- updated name to the correct one - Stefani Castellanos

* Fetch new translations from Transifex

* Fill in release date for 2.7

* Version bump to 2.7 final

* Version bump to 2.7.1

* Move all usage of versioned_static to media methods (wagtail#5694)

* Release notes for wagtail#5694

* Fill in release date for 2.7.1

* Apply proper HTML escaping on StreamField block comparisons

An individual StreamField block in the comparison view may be rendered as a plain value (for blocks that are unchanged, added or deleted) or a diff (for blocks that are changed). In both cases, the output is returned as HTML, but must not contain any unescaped editor-supplied HTML.

For CharBlock, TextBlock and RawHTMLBlock, the block value is escaped so that any HTML tags in the content are shown verbatim.

For RichTextBlock and any other block types that do not override the default comparison behaviour, we take the basic (non-templated) HTML rendering of the block and extract text-only content from it. This is then returned in HTML-escaped form for the plain view, and run through diff_text().to_html() for the diff view (which handles escaping itself).

* Don't mark the translatable string 'None' as safe

* Release notes for 2.7.2

* Version bump to 2.7.2

* fix syntax

* bug fix

* remove invalid import

* fix more imports

* fix testapp migrations

* fix images and core migrations

* fix image field help text

* add js to AdminImageRenditionChooser

* fix image chooser

* continue fixing image chooser

* add missing js files back to image chooser

* add onload to image chooser

* fix search backend

Co-authored-by: Eric Dyken <[email protected]>
Co-authored-by: Matt Westcott <[email protected]>
Co-authored-by: Helen Chapman <[email protected]>
Co-authored-by: Andy Babic <[email protected]>
Co-authored-by: jordan-bauer <[email protected]>
Co-authored-by: Coen van der Kamp <[email protected]>
Co-authored-by: John Carter <[email protected]>
Co-authored-by: Fidel Ramos <[email protected]>
Co-authored-by: Thibaud Colas <[email protected]>
Co-authored-by: Jonny Scholes <[email protected]>
Co-authored-by: Karl Hobley <[email protected]>
Co-authored-by: Karl Hobley <[email protected]>
Co-authored-by: Mikalai Radchuk <[email protected]>
Co-authored-by: jordan_bauer <[email protected]>
Co-authored-by: Tom Dyson <[email protected]>
Co-authored-by: Jaroslaw Zabiello <[email protected]>
Co-authored-by: Jonny <[email protected]>
Co-authored-by: Michael Hearn <[email protected]>
Co-authored-by: William Blackie <[email protected]>
Co-authored-by: Andrew Miller <[email protected]>
Co-authored-by: Michael van Tellingen <[email protected]>
Co-authored-by: Daniele Procida <[email protected]>
Co-authored-by: kevinhowbrook <[email protected]>
Co-authored-by: Rodrigo <[email protected]>
Co-authored-by: Cameron Lamb <[email protected]>
Co-authored-by: Catherine Farman <[email protected]>
Co-authored-by: Kalob Taulien <[email protected]>
Co-authored-by: Iman Syed <[email protected]>
Co-authored-by: mien <[email protected]>
Co-authored-by: Neal Todd <[email protected]>
Co-authored-by: Martey Dodoo <[email protected]>
Co-authored-by: John Carter <[email protected]>
Co-authored-by: Andy Chosak <[email protected]>
Co-authored-by: Samir Shah <[email protected]>
Co-authored-by: rjpruitt16 <[email protected]>
Co-authored-by: Jonathan Liuti <[email protected]>
Co-authored-by: Iman Syed <[email protected]>
Co-authored-by: Mikalai Radchuk <[email protected]>
Co-authored-by: Sergey Fedoseev <[email protected]>
Co-authored-by: Sanyam Khurana <[email protected]>
Co-authored-by: Pavel Denisov <[email protected]>
Co-authored-by: Kalob Taulien <[email protected]>
Co-authored-by: Bertrand Bordage <[email protected]>
Co-authored-by: Zac Connelly <[email protected]>
Co-authored-by: Robert Rollins <[email protected]>
Co-authored-by: pvetch <[email protected]>
Co-authored-by: Bojan Mihelac <[email protected]>
Co-authored-by: Sarath Kumar Somana <[email protected]>
Co-authored-by: Dani Hodovic <[email protected]>
Co-authored-by: Janne Alatalo <[email protected]>
Co-authored-by: Mads Jensen <[email protected]>
Co-authored-by: Colin Klein <[email protected]>
Co-authored-by: Edy <[email protected]>
Co-authored-by: Kiril Staikov <[email protected]>
Co-authored-by: Saptak S <[email protected]>
Co-authored-by: Dawid Bugajewski <[email protected]>
Co-authored-by: Tobias McNulty <[email protected]>
Co-authored-by: Dawn Wages <[email protected]>
Co-authored-by: jacobtm <[email protected]>
Co-authored-by: Brian Whitton <[email protected]>
Co-authored-by: Tim White <[email protected]>
Co-authored-by: Mike Janger <[email protected]>
Co-authored-by: jacobtoppm <[email protected]>
Co-authored-by: Prithvi MK <[email protected]>
Co-authored-by: pySilver <[email protected]>
Co-authored-by: a-mere-peasant <[email protected]>
Co-authored-by: David Thompson <[email protected]>
Co-authored-by: LB (Ben Johnston) <[email protected]>
Co-authored-by: Thijs Baaijen <[email protected]>
Co-authored-by: Andreas Bernacca <[email protected]>
Co-authored-by: frmdstryr <[email protected]>
Co-authored-by: David <[email protected]>
Co-authored-by: Stefani Castellanos <[email protected]>
Co-authored-by: Alex Tomkins <[email protected]>
@CVYY39
Copy link

CVYY39 commented May 14, 2020

Quick fix for my site was to add localhost to the ALLOWED_HOSTS string. Worked like a charm.

@tobyspark
Copy link

I had the same symptoms. I added Wagtail 2.9 to an existing Django 2.2 site, following the documentation. Everything worked, except for page previews in production, which resulted in 400 Bad Request error.

I’ve read through the various issues linked in #5427 and am none the wiser, given a) the fixes already incorporated to Wagtail 2.9 and e.g. I have none of the middleware installed, and no Wagtail site settings beyond WAGTAIL_SITE_NAME.

Adding localhost to the production ALLOWED_HOSTS results in the previews working. But clearly is a bodge. Posting as FYI; this is a fairly vanilla site, I’m surprised by this.

@gasman
Copy link
Collaborator

gasman commented Jul 3, 2020

@tobyspark It sounds like you don't have the correct site hostname set under Settings -> Sites in the Wagtail admin.

Having said that, the intention behind Wagtail's site configuration is that for single-site installations, the out-of-the box setup should continue to work for as long as possible even if the hostname hasn't been filled in - so, for example, the {% pageurl %} tag doesn't include the domain part of the URL. If the only thing standing in the way of a fully-functional site in DEBUG=False mode is the mismatch between the hostname used for previewing and ALLOWED_HOSTS, then we should fix that - I think that could be done by:

  • in make_preview_request, see if the intended hostname for the request is allowed by ALLOWED_HOSTS
  • if not, see if the Wagtail site configuration consists of a single Site record with is_default_site=True (i.e. this Wagtail installation treats all hostnames as equivalent)
  • if so, use the first item in ALLOWED_HOSTS in place of whatever the Site record's hostname says

@gasman gasman reopened this Jul 3, 2020
@tobyspark
Copy link

tobyspark commented Jul 3, 2020

@gasman Correct, and a slight mea-culpa in that I didn’t find those settings as I was using Wagtail when logged-in as an editor not administrator.

Nonetheless, there’s no mention that setting the site name is required in the Integrating Wagtail into a Django project documentation – and, generally, yes your intention is correct and taking the first item in ALLOWED_HOSTS seems a better approach than forcing that parameter to be set.

@lb- lb- added the component:Preview Page lives preview functionality, viewing drafts label Apr 11, 2022
@SebCorbin
Copy link
Contributor

@tobyspark It sounds like you don't have the correct site hostname set under Settings -> Sites in the Wagtail admin.

Having said that, the intention behind Wagtail's site configuration is that for single-site installations, the out-of-the box setup should continue to work for as long as possible even if the hostname hasn't been filled in - so, for example, the {% pageurl %} tag doesn't include the domain part of the URL. If the only thing standing in the way of a fully-functional site in DEBUG=False mode is the mismatch between the hostname used for previewing and ALLOWED_HOSTS, then we should fix that - I think that could be done by:

* in `make_preview_request`, see if the intended hostname for the request is allowed by ALLOWED_HOSTS

* if not, see if the Wagtail site configuration consists of a single Site record with `is_default_site=True` (i.e. this Wagtail installation treats all hostnames as equivalent)

* if so, use the first item in ALLOWED_HOSTS in place of whatever the Site record's hostname says

This won't work for wildcards in ALLOWED_HOSTS

@gasman
Copy link
Collaborator

gasman commented Nov 29, 2023

@SebCorbin That's easily fixed - for * wildcards we're already covered by the first step, and for .example.com we just strip off the leading dot.

@henriquelalves
Copy link

I was also having this problem. My "ALLOWED_HOSTS" had no wildcards, only the hostname of the website, and I couldn't preview any page on Wagtail admin view. I'm using Caddy instead of Nginx.

What fixed it for me was changing the port of the Wagtail site config to "443" instead of the default "80". My Django application is redirecting SSL and had all SECURE_HSTS options, so maybe that was crashing the preview when using an "http" port.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:Preview Page lives preview functionality, viewing drafts type:Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.