NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #5236 most downloaded on PyPI
A Django content management system.
Last release 23 days ago
25 Aug 2026
Release timing varies
gaps range from 9 days to 2 months
Nearly every release is documented
notes for 60 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
13 years old
300 releases · first in 2014
Fix: Reinstate wagtail.models.collections to prevent import errors in migrations (Matt Westcott)
Updates from 6.1rc1:
Update PASSWORD_REQUIRED_TEMPLATE setting to WAGTAIL_PASSWORD_REQUIRED_TEMPLATE with deprecation of previous naming (Saksham Misra, LB (Ben) Johnston)
WAGTAIL_DATE_FORMAT, WAGTAIL_DATETIME_FORMAT, WAGTAIL_TIME_FORMAT are correctly configured (Rohit Sharma, Coen van der Kamp)IndexView using the generic.IndexView (Rohit Sharma, Sage Abdullah, Storm Heg)IndexView using the generic.IndexView (Rohit Sharma, Sage Abdullah, Temidayo Azeez)PageListingViewSet for custom per-page-type page listings (Matt Westcott)ChooseParentView to PageListingViewSet to allow creating pages from custom page listings (Abdelrahman Hamada, Sage Abdullah)djangorestframework to 3.15.1 (Sage Abdullah)IndexView.list_display (Abdelrahman Hamada)STORAGES alias name for WAGTAILIMAGES_RENDITION_STORAGE (Alec Baron)PASSWORD_REQUIRED_TEMPLATE setting to WAGTAIL_PASSWORD_REQUIRED_TEMPLATE with deprecation of previous naming (Saksham Misra, LB (Ben) Johnston)DOCUMENT_PASSWORD_REQUIRED_TEMPLATE setting to WAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE with deprecation of previous naming (Saksham Misra, LB (Ben) Johnston)get_parent (Nigel van Keulen)__str__ for MySQL search index (Jake Howard)date objects on human_readable_date template tag (Jhonatan Lopes)verbose_name in group edit view when listing custom permissions (Sage Abdullah, Neeraj Yetheendran, Omkar Jadhav)make livehtml (Sage Abdullah)LANGUAGE_CODE (Mark Niehues)UnsavedController checks for nested removal/additions of inputs so that the unsaved warning shows in more valid cases when editing a page (Karthik Ayangar)get_add_url() is always used to re-render the add button when the listing is refreshed in viewsets (Sage Abdullah)objects manager (Jhonatan Lopes)get_dummy_request's resulting host name when running tests with ALLOWED_HOSTS = ["*"] (David Buxton)timesince_last_update template tag (Matt Westcott)w-kbd-scope-value with support for global so that specific keyboard shortcuts (e.g. ctrl+s/cmd+s) trigger consistently even when focused on fields (Neeraj Yetheendran)WAGTAIL_ALLOW_UNICODE_SLUGS setting when auto-generating slugs (LB (Ben) Johnston)--purge-only in wagtail_update_image_renditions management command section (Pranith Beeram)6.3.0 with a fix for the missing favicon (Sage Abdullah)wagtail_update_image_renditions management command on the using images page (LB (Ben) Johnston)html.parser (Jake Howard)html.parser & remove html5lib dependency (Jake Howard)Button that only renders links (a element) to Link and remove unused prop & behavior that was non-compliant for aria role usage (Advik Kabra)wagtail.models.AbstractWorkflow model to support future customizations around workflows (Hossein)classnames template tag to handle nested lists of strings, use template tag for admin body element (LB (Ben) Johnston)UploadedDocument and UploadedImage into new UploadedFile model for easier shared code usage (Advik Kabra, Karl Hobley)window.chooserUrls globals, removing the need for inline scripts (Elhussein Almasri)w-init (InitController) to support a detail value to be dispatched on events (Chiemezuo Akujobi)page_breadcrumbs tag to use shared breadcrumbs.html template (Sage Abdullah)keyboard icon to admin icon set (Rohit Sharma)SwapController (LB (Ben) Johnston)w-block/BlockController) to instantiate StreamField blocks (Karthik Ayangar)w-kbd/KeyboardController) (Neeraj Yetheendran)xregexp (IE11 polyfill) along with window.XRegExp global util (LB (Ben) Johnston)urlify to use TypeScript, officially deprecate window.URLify global util (LB (Ben) Johnston)One column per quarter.
Fix: CVE-2024-39317: Regular expression denial-of-service via search query parsing (Jake Howard)
July 11, 2024
---
local:
depth: 1
---
This release addresses a denial-of-service vulnerability in Wagtail. A bug in Wagtail's parse_query_string would result in it taking a long time to process suitably crafted inputs. When used to parse sufficiently long strings of characters without a space, parse_query_string would take an unexpectedly large amount of time to process, resulting in a denial of service.
In an initial Wagtail installation, the vulnerability can be exploited by any Wagtail admin user. It cannot be exploited by end users. If your Wagtail site has a custom search implementation which uses parse_query_string, it may be exploitable by other users (e.g. unauthenticated users).
Many thanks to Jake Howard for reporting and fixing this issue. For further details, please see the CVE-2024-39317 security advisory.
Fix: CVE-2024-35228: Improper handling of insufficient permissions in wagtail.contrib.settings (Victor Miti, Matt Westcott, Jake Howard)
wagtail.contrib.settings (Victor Miti, Matt Westcott, Jake Howard)May 30, 2024
---
local:
depth: 1
---
wagtail.contrib.settingsThis release addresses a permission vulnerability in the Wagtail admin interface. Due to an improperly applied permission check in the wagtail.contrib.settings module, a user with access to the Wagtail admin and knowledge of the URL of the edit view for a settings model can access and update that setting, even when they have not been granted permission over the model. The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin.
Many thanks to Victor Miti for reporting this issue, and Matt Westcott and Jake Howard for the fix. For further details, please see the CVE-2024-35228 security advisory.
Fix: Fix snippet copy view not prefilling form data (Sage Abdullah)
May 21, 2024
---
local:
depth: 1
---
Fix: CVE-2024-32882: Permission check bypass when editing a model with per-field restrictions through wagtail.contrib.settings or ModelViewSet (Ben Mo…
wagtail.contrib.settings or ModelViewSet (Ben Morse, Joshua Munn, Jake Howard, Sage Abdullah)WAGTAIL_ALLOW_UNICODE_SLUGS setting when auto-generating slugs (LB (Ben) Johnston)convert_mariadb_uuids management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)May 1, 2024
---
local:
depth: 1
---
wagtail.contrib.settings or ModelViewSetThis release addresses a permission vulnerability in the Wagtail admin interface. If a model has been made available for editing through the wagtail.contrib.settings module or ModelViewSet, and the permission argument on FieldPanel has been used to further restrict access to one or more fields of the model, a user with edit permission over the model but not the specific field can craft an HTTP POST request that bypasses the permission check on the individual field, allowing them to update its value.
The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin, or by a user who has not been granted edit access to the model in question. The editing interfaces for pages and snippets are also unaffected.
Many thanks to Ben Morse and Joshua Munn for reporting this issue, and Jake Howard and Sage Abdullah for the fix. For further details, please see the CVE-2024-32882 security advisory.
WAGTAIL_ALLOW_UNICODE_SLUGS setting when auto-generating slugs (LB (Ben) Johnston)convert_mariadb_uuids management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with CHAR-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as Data too long for column 'translation_key' at row 1 or Data too long for column 'uuid' at row 1 when creating or editing pages. To fix this, it is necessary to run the convert_mariadb_uuids management command (available as of Wagtail 6.0.3) after upgrading:
./manage.py convert_mariadb_uuids
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.
Fix: Ensure that modal tabs width are not impacted by side panel opening (LB (Ben) Johnston)
make livehtml (Sage Abdullah)get_add_url() is always used to re-render the add button when the listing is refreshed in viewsets (Sage Abdullah)modal-workflow.js script usage to base admin template instead of ad-hoc imports so that choosers work in ModelViewSets (Elhussein Almasri)InlinePanel is included by default in ModelViewSet's create and edit views (Sage Abdullah)extra_footer_actions block in page create/edit templates (LB (Ben) Johnston, Sage Abdullah)6.3.0 with a fix for the missing favicon (Sage Abdullah)April 3, 2024
---
local:
depth: 1
---
make livehtml (Sage Abdullah)get_add_url() is always used to re-render the add button when the listing is refreshed in viewsets (Sage Abdullah)modal-workflow.js script usage to base admin template instead of ad-hoc imports so that choosers work in ModelViewSets (Elhussein Almasri)InlinePanel is included by default in ModelViewSet's create and edit views (Sage Abdullah)extra_footer_actions block in page create/edit templates (LB (Ben) Johnston, Sage Abdullah)6.3.0 with a fix for the missing favicon (Sage Abdullah)Fix: Ensure BooleanRadioSelect uses the same styles as RadioSelect (Thibaud Colas)
BooleanRadioSelect uses the same styles as RadioSelect (Thibaud Colas)collectstatic when ManifestStaticFilesStorage is in use (Matt Westcott)February 15, 2024
---
local:
depth: 1
---
BooleanRadioSelect uses the same styles as RadioSelect (Thibaud Colas)collectstatic when ManifestStaticFilesStorage is in use (Matt Westcott)Update settings file in project settings to address Django 4.2 deprecations (Sage Abdullah)
🎉 Special 10th anniversary release! 🎉
search_index option to StreamField blocks to control whether the block is indexed for searching (Vedant Pandey)UniqueConstraint in place of unique_together for TranslatableMixin's system check (Temidayo Azeez, Sage Abdullah)IndexView.get_add_url() in snippets index view template (Christer Jensen, Sage Abdullah)Page.permissions_for_user() to be overridden by specific page types (Sébastien Corbin)extra_actions blocks to Snippets and generic index templates (Bhuvnesh Sharma)panels / edit_handler on ModelViewSet (Sage Abdullah)PagePermissionPolicy in wagtail.permissions module (Sage Abdullah)max_length (Elhussein Almasri)TypedTableBlock (Tommaso Amici, Cynthia Kiser)TableBlock header controls to a field that requires user input (Bhuvnesh Sharma, Aman Pandey, Cynthia Kiser)WAGTAILADMIN_LOGIN_URL setting to allow customising the login URL (Neeraj Yetheendran)DrilldownController and w-drilldown component to support drilldown menus (Thibaud Colas)caption on admin UI Table component (Aman Pandey)SnippetViewSet & ModelViewSet to support being copied (Shlomo Markowitz)STORAGES setting introduced in Django 4.2 (phijma-leukeleu)index_results.html or index_results_template_name override on initial load (Stefan Hammer)last_published_by_user (Chiemezuo Akujobi)alias and specific (Tomasz Knapik)ActionController explicitly checks for elements that allow select functionality (Nandini Arora)FormSubmissionsPanel on Django 5.0 when creating a new form page (Matt Westcott)MultipleChooserPanel modal works correctly when USE_THOUSAND_SEPARATOR is True for pages with ids over 1,000 (Sankalp, Rohit Sharma)th) for visual spacing, ensure this is ignored by accessibility tooling (V Rohitansh)SiteSetting.DoesNotExist error when retrieving settings for an unrecognised site (Nick Smith)exclude_fields_in_copy are correctly excluded in new copies, resolving to the default value (Elhussein Almasri)default_ordering set on IndexView is preserved if ModelViewSet does not specify an explicit ordering (Cynthia Kiser)_() within templates (Chiemezuo Akujobi)Page model reference get_children documentation (Salvo Polizzi)get_upload_to methods (Osaf AliSayed, Dharmik Gangani)body.ready) from multiple JavaScript implementations to one Stimulus controller w-init (Chiemezuo Akujobi)arg=_('...') in all wagtailadmin module templates (Chiemezuo Akujobi)ruff and replace black with ruff format (John-Scott Atlakson)laces library (Tibor Leupold){% formattedfield %} tag to replace direct use of wagtailadmin/shared/field.html (Matt Westcott)ActionController to have a noop method to more easily leverage standalone Stimulus action options (Nandini Arora)skipLibCheck for TypeScript (LB (Ben) Johnston)CloneController to auto clear the added content after a set duration (LB (Ben) Johnston)BaseListingView (Matt Westcott)c-, o-, u-, t-, is- prefixes (Thibaud Colas)initTooltips in favour of Stimulus controller (LB (Ben) Johnston)InitController to allow for custom event dispatching when ready (Aditya, LB (Ben) Johnston)UnsavedController (Sai Srikar Dumpeti, LB (Ben) Johnston)OrderableController with a more accessible solution (Aman Pandey, LB (Ben) Johnston)FileResponse when serving files such as Images or Documents (Jake Howard)WidgetWithScript base widget class (LB (Ben) Johnston)4.2, 5.0
3.8, 3.9, 3.10, 3.11, 3.12
5.2 LTS
3.2, 4.1, 4.2, 5.0 [ 1 ]
3.8, 3.9, 3.10, 3.11, 3.12
February 7, 2024
---
local:
depth: 1
---
This release adds support for Django 5.0. The support has also been backported to Wagtail 5.2 LTS.
A new developer tutorial series has been added to the documentation. This series builds upon the pre-existing , going through the creation and deployment of a portfolio website.
This tutorial series was created by Damilola Oladele as part of the Google Season of Docs program, with support from Meagen Voss, and Thibaud Colas. We also thank Storm Heg, Kalob Taulien, Kátia Nakamura, Mariusz Felisiak, and Rachel Smith for their support and feedback as part of the project.
Following design improvements to the page listing view, Wagtail now provides a unified search and filtering interface for all listings. This will improve navigation capabilities, particularly for sites with a large number of pages or where content tends to use a flat structure.
In this release, the universal listing interface is available for Pages, Snippets, and Forms. For pages, the UI includes the following filters out of the box:
This feature was developed by Ben Enright, Matt Westcott, Nick Lee, Thibaud Colas, and Sage Abdullah.
The admin interface now supports right-to-left languages, such as Persian, Arabic, and Hebrew. Though there are still some areas that need improvement, all admin views will now be displayed in the correct direction. Review our UI guidelines for guidance on supporting right-to-left languages in admin interface customizations.
Thank you to Thibaud Colas, Badr Fourane, and Sage Abdullah for their work on this long-requested improvement.
The built-in accessibility checker now displays as a side panel within page and snippet editors supporting preview. The new "Checks" side panel only shows accessibility-related issues for pages with the userbar enabled in this release, but will be updated to support any content checks in the future.
This feature was implemented by Nick Lee, Thibaud Colas, and Sage Abdullah.
The new Page types report provides a breakdown of the number of pages for each type. It helps answer questions such as:
This feature was developed by Jhonatan Lopes, as part of a sponsorship by the Mozilla Foundation.
This release comes with a high number of accessibility improvements across the admin interface.
TypedTableBlock (Tommaso Amici, Cynthia Kiser)TableBlock header controls to a field that requires user input (Bhuvnesh Sharma, Aman Pandey, Cynthia Kiser)caption on admin UI Table component (Aman Pandey)th) for visual spacing, ensure this is ignored by accessibility tooling (V Rohitansh)search_index option to StreamField blocks to control whether the block is indexed for searching (Vedant Pandey)UniqueConstraint in place of unique_together for {class}~wagtail.models.TranslatableMixin's system check (Temidayo Azeez, Sage Abdullah)IndexView.get_add_url() in snippets index view template (Christer Jensen, Sage Abdullah)Page.permissions_for_user() to be overridden by specific page types (Sébastien Corbin)extra_actions blocks to Snippets and generic index templates (Bhuvnesh Sharma)panels / edit_handler on ModelViewSet (Sage Abdullah)PagePermissionPolicy in wagtail.permissions module (Sage Abdullah)max_length (Elhussein Almasri)WAGTAILADMIN_LOGIN_URL setting to allow customizing the login URL (Neeraj Yetheendran)DrilldownController and w-drilldown component to support drilldown menus (Thibaud Colas)SnippetViewSet & ModelViewSet to support being copied, this can be disabled by copy_view_enabled = False (Shlomo Markowitz)STORAGES setting introduced in Django 4.2 (phijma-leukeleu)index_results.html or index_results_template_name override on initial load (Stefan Hammer)last_published_by_user (Chiemezuo Akujobi)alias and specific (Tomasz Knapik)ActionController explicitly checks for elements that allow select functionality (Nandini Arora)FormSubmissionsPanel on Django 5.0 when creating a new form page (Matt Westcott)MultipleChooserPanel modal works correctly when USE_THOUSAND_SEPARATOR is True for pages with ids over 1,000 (Sankalp, Rohit Sharma)SiteSetting.DoesNotExist error when retrieving settings for an unrecognized site (Nick Smith)exclude_fields_in_copy are correctly excluded in new copies, resolving to the default value (Elhussein Almasri)default_ordering set on IndexView is preserved if ModelViewSet does not specify an explicit ordering (Cynthia Kiser)_() within templates (Chiemezuo Akujobi)MultipleChooserPanel may require a chooser viewset and how the functionality is expected to work (Andy Chosak)Page model reference get_children documentation (Salvo Polizzi)As part of ongoing refactorings, we have migrated several views to use generic class-based views. This allows for easier extensibility and better code reuse.
body.ready) from multiple JavaScript implementations to one Stimulus controller w-init (Chiemezuo Akujobi)arg=_('...') in all wagtailadmin module templates (Chiemezuo Akujobi)ruff and replace black with ruff format (John-Scott Atlakson)laces library (Tibor Leupold){% formattedfield %} tag to replace direct use of wagtailadmin/shared/field.html (Matt Westcott)ActionController to have a noop method to more easily leverage standalone Stimulus action options (Nandini Arora)skipLibCheck for TypeScript (LB (Ben) Johnston)CloneController to auto clear the added content after a set duration (LB (Ben) Johnston)BaseListingView (Matt Westcott)c-, o-, u-, t-, is- prefixes (Thibaud Colas)initTooltips in favor of Stimulus controller (LB (Ben) Johnston)InitController to allow for custom event dispatching when ready (Aditya, LB (Ben) Johnston)UnsavedController (Sai Srikar Dumpeti, LB (Ben) Johnston)OrderableController with a more accessible solution (Aman Pandey, LB (Ben) Johnston)FileResponse when serving files such as Images or Documents (Jake Howard)WidgetWithScript base widget class (LB (Ben) Johnston)Features previously deprecated in Wagtail 4.2, 5.0 and 5.1 have been fully removed. For additional details on these changes, see:
The most significant changes are highlighted below.
The wagtail.contrib.modeladmin app has been removed. If you wish to continue using it, it is available as the external package wagtail-modeladmin.
Query model moved to wagtail.contrib.search_promotionsThe Query model (used to log search queries performed by users, to identify commonly searched terms) is no longer part of the wagtail.search module; it can now be found in the optional wagtail.contrib.search_promotions app. When updating code to import the model from the new location, ensure that you have added wagtail.contrib.search_promotions to your INSTALLED_APPS setting - failing to do this may result in a spurious migration being created within the core wagtail app.
The Elasticsearch 5 and 6 backends have been removed. If you are using one of these backends, you will need to upgrade to Elasticsearch 7 or 8 before upgrading to Wagtail 6.0.
use_json_field=TrueThe use_json_field argument to StreamField is no longer required, and can be removed. StreamField now consistently uses JSONField for its database representation, and Wagtail 5.0 required older TextField-based streams to be migrated. As such, use_json_field no longer has any effect.
WAGTAILADMIN_GLOBAL_PAGE_EDIT_LOCK setting is no longer recognized and should be replaced with WAGTAILADMIN_GLOBAL_EDIT_LOCK.wagtail.models.UserPagePermissionsProxy class and get_pages_with_direct_explore_permission, get_explorable_root_page and users_with_page_permission functions have been removed; equivalent functionality exists in the wagtail.permission_policies.pages.PagePermissionPolicy class.permission_type field of the GroupPagePermission model has been removed; the permission field (a foreign key to Django's Permission model) should be used instead.partial_match argument on SearchField and on search methods has been removed. AutocompleteField and the autocomplete method should be used instead.insert_editor_css hook has been removed; the insert_global_admin_css hook should be used instead.wagtail.contrib.frontend_cache module now supports azure-mgmt-cdn version 10 and azure-mgmt-frontdoor version 1 as its minimum supported versions.Task.page_locked_for_user method has been removed; Task.locked_for_user should be used instead.{% icon %} template tag no longer accepts class_name as an argument; classname should be used instead.wagtail.tests.utils module has been removed and can now be found at wagtail.test.utils.wagtailadmin/shared/field_as_li.html has been removed, and should be replaced with wagtailadmin/shared/field.html enclosed in an <li> tag.wagtail:show and wagtail:hide on showing and hiding dialogs have been removed; w-dialog:show and w-dialog:hide should be used instead.headerSearch, initTagField, cancelSpinner and unicodeSlugsEnabled have been removed; these should be replaced with Stimulus controllers.Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with CHAR-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as Data too long for column 'translation_key' at row 1 or Data too long for column 'uuid' at row 1 when creating or editing pages. To fix this, it is necessary to run the convert_mariadb_uuids management command (available as of Wagtail 6.0.3) after upgrading:
./manage.py convert_mariadb_uuids
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.
SnippetViewSet & ModelViewSet copy view enabled by defaultThe newly introduced copy view will be enabled by default for all ModelViewSet and SnippetViewSet classes.
This can be disabled by setting copy_view_enabled = False, for example.
class PersonViewSet(SnippetViewSet):
model = Person
# ...
copy_view_enabled = False
class PersonViewSet(ModelViewSet):
model = Person
# ...
copy_view_enabled = False
See for additional details about this feature.
Django versions before 4.2 are no longer supported as of this release; please upgrade to Django 4.2 or above before upgrading Wagtail.
SlugInput widget is now the default for SlugField fieldsIn Wagtail 5.0 a new SlugInput admin widget was added to support slug behavior in Page and Page copy forms. This widget was included by default if the promote_panels fields layout was customized, causing confusion.
As of this release, any forms that inherit from WagtailAdminModelForm (includes page and snippet model editing) will now use the SlugInput by default on all models with SlugField fields.
Previously, the widget had to be explicitly added.
from wagtail.admin.widgets.slug import SlugInput
# ... other imports
class MyPage(Page):
promote_panels = [
FieldPanel("slug", widget=SlugInput),
# ... other panels
]
Keeping the widget as above is fine, but will no longer be required. The JavaScript field behavior will be included by default.
# ... imports
class MyPage(Page):
promote_panels = [
FieldPanel("slug"),
# ... other panels
]
If you do not want this for some reason, you will now need to declare a different widget.
from django.forms.widgets import TextInput
# ... other imports
class MyPage(Page):
promote_panels = [
FieldPanel("slug", widget=TextInput), # use a plain text field
# ... other panels
]
Page objects or subclasses of DraftStateMixinBefore this release, the database record of a Page or any subclass of DraftStateMixin either contained the live data (if published), the state of the last published version (if unpublished), or the state of the first revision (if never published). Subsequent draft edits would create new Revision records, but the main database record would not be updated. As a result, the database record could lag substantially behind the current state of the object, causing unexpected behavior particularly when unique constraints are in use.
As of this release, the database record of a non-live object will be updated to reflect the draft state of the object. This is unlikely to have a visible effect on existing sites, since the admin backend works with the Revision records while the site front-end typically filters out non-live objects. However, any code that relies on the database record being untouched by draft edits (for example, using it to store a specific approved / archived state of the page) may need to be updated.
filter_queryset and get_filtered_queryset methods no longer return filtersThe undocumented internal methods filter_queryset(queryset) on wagtail.admin.views.generic.IndexView, and get_filtered_queryset() on wagtail.admin.views.reports.ReportView, now return just the filtered queryset; previously they returned a tuple of (filters, queryset). The filterset instance is always available as the cached property self.filters.
window.enableDirtyFormCheck functionThe admin frontend window.enableDirtyFormCheck will be removed in a future release and as of this release only supports the basic initialization.
The previous approach was to call a window global function as follows.
window.enableDirtyFormCheck('.my-form', { alwaysDirty: true, confirmationMessage: 'You have unsaved changes'});
The new approach will be data attribute driven as follows.
<form
method="POST"
data-controller="w-unsaved"
data-action="w-unsaved#submit beforeunload@window->w-unsaved#confirm change->w-unsaved#check keyup->w-unsaved#check"
data-w-unsaved-confirm-value="This page has unsaved changes." // equivalent to `confirmationMessage`.
data-w-unsaved-force-value="true" // equivalent to `alwaysDirty`.
data-w-unsaved-watch-value="edits comments" // can add 'comments' if comments is enabled, defaults to only 'edits'.
>
... form contents
</form>
data-tippy-content attribute support will be removedThe implementation of the JS tooltips have been fully migrated to the Stimulus w-tooltip/TooltipController implementation.
Dynamic support for any data-tippy-content="..." usage will be removed this release, for example, within chooser modals or dynamic html response data.
Some minimal backwards compatibility support for data-tippy-content will work until a future release, but only in the initial HTML response on a page.
These HTML data attributes were not documented, but if any custom code implemented custom tooltips, these will need to be changed.
| Old | New | Notes |
|---|---|---|
data-controller="w-tooltip" |
Required, new addition for any usage | |
data-tippy-content="{% trans 'History' %}" |
data-w-tooltip-content-value="{% trans 'History' %}" |
Required |
data-tippy-offset="[12, 24]" |
data-w-tooltip-offset-value="[12, 24]" |
Optional, default is no offset |
data-tippy-placement="top" |
data-w-tooltip-placement-value="top" |
Optional, default is 'bottom' |
WidgetWithScript base widget classThe undocumented WidgetWithScript class that used inline scripts to attach JavaScript to widgets will be removed in a future release.
This approach creates security risks and will not be compliant with CSP support. Instead, it's recommended that all similar requirements migrate to use the recommended Stimulus JS integration approach.
A full example of how to build this has been documented on extending client-side behavior, a basic example is below.
from django.forms import Media, widgets
class CustomRichTextArea(WidgetWithScript, widgets.Textarea):
def render_js_init(self, id_, name, value):
return f"window.customEditorInitScript({json.dumps(id_)});"
@property
def media(self):
return Media(js=["vendor/custom-editor.js"])
from django.forms import Media, widgets
class CustomRichTextArea(widgets.Textarea):
def build_attrs(self, *args, **kwargs):
attrs = super().build_attrs(*args, **kwargs)
attrs["data-controller"] = "custom-editor"
@property
def media(self):
return Media(js=["vendor/custom-editor.js", "js/custom-editor-controller.js"])
// myapp/static/js/custom-editor-controller.js
class CustomEditorController extends window.StimulusModule.Controller {
connect() {
window.customEditorInitScript(this.element.id);
}
}
window.wagtail.app.register('custom-editor', CustomEditorController);
Update settings file in project settings to address Django 4.2 deprecations (Sage Abdullah)
search_index option to StreamField blocks to control whether the block is indexed for searching (Vedant Pandey)UniqueConstraint in place of unique_together for TranslatableMixin's system check (Temidayo Azeez, Sage Abdullah)IndexView.get_add_url() in snippets index view template (Christer Jensen, Sage Abdullah)Page.permissions_for_user() to be overridden by specific page types (Sébastien Corbin)extra_actions blocks to Snippets and generic index templates (Bhuvnesh Sharma)panels / edit_handler on ModelViewSet (Sage Abdullah)PagePermissionPolicy in wagtail.permissions module (Sage Abdullah)max_length (Elhussein Almasri)TypedTableBlock (Tommaso Amici, Cynthia Kiser)TableBlock header controls to a field that requires user input (Bhuvnesh Sharma, Aman Pandey, Cynthia Kiser)WAGTAILADMIN_LOGIN_URL setting to allow customising the login URL (Neeraj Yetheendran)DrilldownController and w-drilldown component to support drilldown menus (Thibaud Colas)caption on admin UI Table component (Aman Pandey)SnippetViewSet & ModelViewSet to support being copied (Shlomo Markowitz)STORAGES setting introduced in Django 4.2 (phijma-leukeleu)index_results.html or index_results_template_name override on initial load (Stefan Hammer)last_published_by_user (Chiemezuo Akujobi)alias and specific (Tomasz Knapik)ActionController explicitly checks for elements that allow select functionality (Nandini Arora)FormSubmissionsPanel on Django 5.0 when creating a new form page (Matt Westcott)MultipleChooserPanel modal works correctly when USE_THOUSAND_SEPARATOR is True for pages with ids over 1,000 (Sankalp, Rohit Sharma)th) for visual spacing, ensure this is ignored by accessibility tooling (V Rohitansh)SiteSetting.DoesNotExist error when retrieving settings for an unrecognised site (Nick Smith)exclude_fields_in_copy are correctly excluded in new copies, resolving to the default value (Elhussein Almasri)default_ordering set on IndexView is preserved if ModelViewSet does not specify an explicit ordering (Cynthia Kiser)_() within templates (Chiemezuo Akujobi)Page model reference get_children documentation (Salvo Polizzi)body.ready) from multiple JavaScript implementations to one Stimulus controller w-init (Chiemezuo Akujobi)arg=_('...') in all wagtailadmin module templates (Chiemezuo Akujobi)ruff and replace black with ruff format (John-Scott Atlakson)laces library (Tibor Leupold){% formattedfield %} tag to replace direct use of wagtailadmin/shared/field.html (Matt Westcott)ActionController to have a noop method to more easily leverage standalone Stimulus action options (Nandini Arora)skipLibCheck for TypeScript (LB (Ben) Johnston)CloneController to auto clear the added content after a set duration (LB (Ben) Johnston)BaseListingView (Matt Westcott)c-, o-, u-, t-, is- prefixes (Thibaud Colas)initTooltips in favour of Stimulus controller (LB (Ben) Johnston)InitController to allow for custom event dispatching when ready (Aditya, LB (Ben) Johnston)UnsavedController (Sai Srikar Dumpeti, LB (Ben) Johnston)OrderableController with a more accessible solution (Aman Pandey, LB (Ben) Johnston)FileResponse when serving files such as Images or Documents (Jake Howard)WidgetWithScript base widget class (LB (Ben) Johnston)Fix: Prevent database error when calling permission_order.register on app ready (Daniel Kirkham, Matt Westcott)
StreamChildrenToListBlockOperation from duplicating data across multiple StreamField instances (Joshua Munn)February 3, 2025
---
local:
depth: 1
---
StreamChildrenToListBlockOperation from duplicating data across multiple StreamField instances (Joshua Munn)Fix: Prevent multiple URLs from being combined into one when pasting links into a rich text input (Thibaud Colas)
November 1, 2024
---
local:
depth: 1
---
Fix: CVE-2024-39317: Regular expression denial-of-service via search query parsing (Jake Howard)
July 11, 2024
---
local:
depth: 1
---
This release addresses a denial-of-service vulnerability in Wagtail. A bug in Wagtail's parse_query_string would result in it taking a long time to process suitably crafted inputs. When used to parse sufficiently long strings of characters without a space, parse_query_string would take an unexpectedly large amount of time to process, resulting in a denial of service.
In an initial Wagtail installation, the vulnerability can be exploited by any Wagtail admin user. It cannot be exploited by end users. If your Wagtail site has a custom search implementation which uses parse_query_string, it may be exploitable by other users (e.g. unauthenticated users).
Many thanks to Jake Howard for reporting and fixing this issue. For further details, please see the CVE-2024-39317 security advisory.
Fix: Respect WAGTAIL_ALLOW_UNICODE_SLUGS setting when auto-generating slugs (LB (Ben) Johnston)
WAGTAIL_ALLOW_UNICODE_SLUGS setting when auto-generating slugs (LB (Ben) Johnston)convert_mariadb_uuids management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)May 1, 2024
---
local:
depth: 1
---
WAGTAIL_ALLOW_UNICODE_SLUGS setting when auto-generating slugs (LB (Ben) Johnston)convert_mariadb_uuids management command to assist with upgrading to Django 5.0+ on MariaDB (Matt Westcott)Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with CHAR-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as Data too long for column 'translation_key' at row 1 or Data too long for column 'uuid' at row 1 when creating or editing pages. To fix this, it is necessary to run the convert_mariadb_uuids management command (available as of Wagtail 5.2.5) after upgrading:
./manage.py convert_mariadb_uuids
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.
Fix: Prevent TitleFieldPanel from raising an error when the slug field is missing or read-only (Rohit Sharma)
April 3, 2024
---
local:
depth: 1
---
Fix: Prevent a ValueError with FormSubmissionsPanel on Django 5.0 when creating a new form page (Matt Westcott)
FormSubmissionsPanel on Django 5.0 when creating a new form page (Matt Westcott)January 23, 2024
---
local:
depth: 1
---
FormSubmissionsPanel on Django 5.0 when creating a new form page (Matt Westcott)Fix: Use a visible border and background color to highlight active formatting in the rich text toolbar (Cassidy Pittman)
index_results.html or index_results_template_name override on initial load (Stefan Hammer)last_published_by_user (Chiemezuo Akujobi)December 6, 2023
---
local:
depth: 1
---
This release adds support for Django 5.0.
index_results.html or index_results_template_name override on initial load (Stefan Hammer)Fix: Add a fallback background for the editing preview iframe for sites without a background (Ian Price)
decorate_paginated_queryset before pagination / filtering (Alex Tomkins){% picture ... as ... %} template tag (Rezyapkin)November 16, 2023
---
local:
depth: 1
---
decorate_paginated_queryset before pagination / filtering (Alex Tomkins){% picture ... as ... %} template tag (Rezyapkin)Maintenance: Deprecate legacy URL redirects in ModelViewSet and SnippetViewSet (Sage Abdullah)
wagtailcache & wagtailpagecache (Jake Howard)field.html template (Sage Abdullah)SnippetViewSet menu registration mechanism to base ViewSet class (Sage Abdullah)ModelViewSet (Sage Abdullah)SnippetViewSet template override mechanism to ModelViewSet (Sage Abdullah)SnippetViewSet.list_display to ModelViewSet (Sage Abdullah)wagtail.publish log action on aliases when they are created from live source pages or the source page is published (Dan Braghis)wagtail.unpublish log action on aliases when source page is unpublished (Dan Braghis)IndexView (Sage Abdullah)list_filter, filterset_class, search_fields, search_backend_name, list_export, export_filename, list_per_page, and ordering from SnippetViewSet to ModelViewSet (Sage Abdullah, Cynthia Kiser)IndexView and CreateView (Sage Abdullah)IndexView.export_headings via ModelViewSet (Christer Jensen, Sage Abdullah)get_object_list method on ChooserViewSet (Matt Westcott)linked_fields mechanism on chooser widgets to allow choices to be limited by fields on the calling page (Matt Westcott)TableBlock with the mergedCells option (Gareth Palmer)InlinePanel, focus will now shift to that content similar to StreamField (Faishal Manzar)placement in the human_readable_date tooltip template tag (Rohit Sharma)ModelViewSet views (Sage Abdullah){% component %} tag (Matt Westcott)PagesAPIViewSet override default Page model via the model attribute (Neeraj Yetheendran, Herbert Poul)ModelViewSet to be used with models that have non-integer primary keys (Sage Abdullah)HistoryView from snippets and add it to ModelViewSet (Sage Abdullah)UsageView to ModelViewSet (Sage Abdullah)IndexView (Sage Abdullah)wagtail_update_image_renditions management command (Faishal Manzar)hashlib.file_digest if available (Python 3.11+) (Jake Howard)Block.get_template to allow varying template based on value (Florian Delizy)InlinePanel DOM events for when ready and when items added or removed (Faishal Manzar)picture template tag for Django Templates and Jinja (Thibaud Colas)srcset_image template tag for Django Templates and Jinja (Thibaud Colas)Filter instances as input for AbstractImage.get_renditions() (Thibaud Colas)FieldPanel('title') examples to use the recommended TitleFieldPanel('title') panel (Chinedu Ihedioha)purge_revisions management command now respects revisions that have a on_delete=PROTECT foreign key relation and won't delete them (Neeraj P Yetheendran, Meghana Reddy, Sage Abdullah, Storm Heg)FieldBlocks correctly set the required and aria-describedby attributes (Storm Heg)PublishMenuItem to more easily support overriding its label via construct_page_action_menu (Sébastien Corbin)non_fields_errors for any custom form validation (Sébastien Corbin)WAGTAIL_EMAIL_MANAGEMENT_ENABLED setting by not showing 'email' if disabled (Omkar Jadhav)ViewSet and ModelViewSet (Sage Abdullah)WAGTAILADMIN_BASE_URL on "Integrating Wagtail into a Django project" page (Shreshth Srivastava)WAGTAILADMIN_RICH_TEXT_EDITORS setting (Charlie Sue)python3-venv on Ubuntu (Brian Mugo)WagtailTestUtils.get_soup() method for testing HTML content (Storm Heg, Sage Abdullah)ViewSet subclasses to customise url_prefix and url_namespace logic (Matt Westcott)SnippetViewSet registration code (Sage Abdullah)IndexView.results_template_name to results.html (Sage Abdullah)w-bulk Stimulus implementation (LB (Ben) Johnston)w-message controller (LB (Ben) Johnston, Hussain Saherwala)stubs.js to prevent Storybook from crashing (LB (Ben) Johnston)slim_header.html template (Sage Abdullah)slim_header.html template to reduce code duplication (Sage Abdullah)imghdr (Jake Howard)imghdr with Willow's built-in MIME type detection (Jake Howard)data-tippy HTML attribute usage to the Stimulus data-*-value attributes for w-tooltip & w-dropdown (Subhajit Ghosh, LB (Ben) Johnston)@total_ordering usage with comparison functions implementation (Virag Jain)<script type="text/django-form-template"><-/script> template approach with HTML template elements in InlinePanel and expanding formset (Mansi Gundre, Subhajit Ghosh, LB (Ben) Johnston)ModelViewSet and SnippetViewSet (Sage Abdullah)lru_cache usage (Jake Howard)date_since in get_most_popular inside search_promotions.models.Query (TopDevPros)classname (not classnames) attributes for all MenuItem usage, including deprecation warnings (LB (Ben) Johnston)classname (not classnames) attribute within the wagtail.images.formats.Format instance, including deprecation warnings (LB (Ben) Johnston)context argument of construct_snippet_listing_buttons hook (Sage Abdullah)search.Query & search.QueryDailyHits model, move final set of templates from the admin search module to the search promotions contrib module (LB (Ben) Johnston)InspectView to ModelViewSet (Sage Abdullah)reset method to support Stimulus driven dynamic field resets via the w-action controller (Chiemezuo Akujobi)notify target on the Stimulus dialog for dispatching events internally (Chiemezuo Akujobi)November 1, 2023
---
local:
depth: 1
---
Wagtail 5.2 is designated a Long Term Support (LTS) release. Long Term Support releases will continue to receive maintenance updates as necessary to address security and data-loss related issues, up until the next LTS release (typically a period of 12 months).
The page explorer listing view has been redesigned to allow improved navigation and searching. This feature was developed by Ben Enright, Matt Westcott, Thibaud Colas and Sage Abdullah.
OpenSearch is now formally supported as an alternative to Elasticsearch. For configuration details, see OpenSearch configuration. This feature was developed by Matt Westcott.
Wagtail has new template tags to reduce the loading time and environmental footprint of images:
picture tag generates images in multiple formats and-or sizes in one batch, creating an HTML <picture> tag.srcset_image tag generates images in multiple sizes, creating an <img> tag with a srcset attribute.As an example, the picture tag allows generating six variants of an image in one go:
{% picture page.photo format-{avif,webp,jpeg} width-{400,800} sizes="80vw" %}
This outputs:
<picture>
<source sizes="80vw" srcset="/media/images/pied-wagtail.width-400.avif 400w, /media/images/pied-wagtail.width-800.avif 800w" type="image/avif">
<source sizes="80vw" srcset="/media/images/pied-wagtail.width-400.webp 400w, /media/images/pied-wagtail.width-800.webp 800w" type="image/webp">
<img sizes="80vw" srcset="/media/images/pied-wagtail.width-400.jpg 400w, /media/images/pied-wagtail.width-800.jpg 800w" src="/media/images/pied-wagtail.width-400.jpg" alt="A pied Wagtail" width="400" height="300">
</picture>
We expect those changes to greatly reduce the weight of images for all Wagtail sites. We encourage all site implementers to consider using them to improve the performance of the sites and reduce their carbon footprint. For further details, For more details, see and . Those new template tags are also supported in Jinja templates, see for the Jinja API.
This feature was developed by Paarth Agarwal and Thibaud Colas as part of the Google Summer of Code program and a partnership with the Green Web Foundation and Green Coding Berlin, with support from Dan Braghiș, Thibaud Colas, Sage Abdullah, Arne Tarara (Green Coding Berlin), and Chris Adams (Green Web Foundation). We also thank Aman Pandey for introducing AVIF support in Wagtail 5.1, Andy Babic for creating AbstractImage.get_renditions() in the same release; and Storm Heg, Mitchel Cabuloy, Coen van der Kamp, Tom Dyson, and Chris Lawton for their feedback on RFC 71.
Wagtail now officially supports client-side admin customizations with Stimulus. The developer documentation has a dedicated page about . This covers fundamental topics of client-side extensibility, such as:
Thank you to core contributor LB (Ben) Johnston for writing this documentation.
ModelViewSet improvementsSeveral features from {class}~wagtail.snippets.views.snippets.SnippetViewSet have been implemented in {class}~wagtail.admin.viewsets.model.ModelViewSet, allowing you to use them without registering your models as snippets. For more details on using ModelViewSet, refer to .
SnippetViewSet menu registration mechanism to base ViewSet class (Sage Abdullah)SnippetViewSet template override mechanism to ModelViewSet (Sage Abdullah)SnippetViewSet.list_display to ModelViewSet (Sage Abdullah)list_filter, filterset_class, search_fields, search_backend_name, list_export, export_filename, list_per_page, and ordering from SnippetViewSet to ModelViewSet (Sage Abdullah, Cynthia Kiser)IndexView and CreateView (Sage Abdullah)IndexView (Sage Abdullah)UsageView to ModelViewSet (Sage Abdullah)InspectView to ModelViewSet (Sage Abdullah)HistoryView from snippets and add it to ModelViewSet (Sage Abdullah)ModelViewSet views (Sage Abdullah)ModelViewSet to be used with models that have non-integer primary keys (Sage Abdullah)ModelViewSet (Sage Abdullah)In addition, the following new features have been added to the generic admin views as part of ModelViewSet, which can also be used with SnippetViewSet.
IndexView.export_headings via ModelViewSet (Christer Jensen, Sage Abdullah)IndexView (Sage Abdullah)Several tweaks have been made to the admin user interface which we hope will make it easier to use.
Promoted search result entries can now use an external URL along with custom link text, instead of linking to a page within Wagtail. This makes it easier to manage promoted content across multiple websites. Thank you to TopDevPros, and Brad Busenius from University of Chicago Library.
wagtailcache and wagtailpagecache template tags to ensure previewing Pages or Snippets will not be cached (Jake Howard)field.html template (Sage Abdullah)wagtail.publish log action on aliases when they are created from live source pages or the source page is published (Dan Braghis)wagtail.unpublish log action on aliases when source page is unpublished (Dan Braghis)get_object_list method on ChooserViewSet (Matt Westcott)linked_fields mechanism on chooser widgets to allow choices to be limited by fields on the calling page (Matt Westcott)TableBlock with the mergedCells option (Gareth Palmer)InlinePanel, focus will now shift to that content similar to StreamField (Faishal Manzar)placement in human_readable_date the tooltip template tag (Rohit Sharma){% component %} tag (Matt Westcott)PagesAPIViewSet override default Page model via the model attribute (Neeraj Yetheendran, Herbert Poul)wagtail_update_image_renditions management command (Faishal Manzar)hashlib.file_digest if available (Python 3.11+) (Jake Howard)Block.get_template to allow varying template based on value (Florian Delizy)InlinePanel DOM events for when ready and when items added or removed (Faishal Manzar)Filter instances as input for AbstractImage.get_renditions() (Thibaud Colas)purge_revisions management command now respects revisions that have an on_delete=PROTECT foreign key relation and won't delete them (Neeraj P Yetheendran, Meghana Reddy, Sage Abdullah, Storm Heg)FieldBlocks correctly set the required and aria-describedby attributes (Storm Heg)PublishMenuItem to more easily support overriding its label via construct_page_action_menu (Sébastien Corbin)non_fields_errors for any custom form validation (Sébastien Corbin)WAGTAIL_EMAIL_MANAGEMENT_ENABLED setting by not showing 'email' if disabled (Omkar Jadhav)ViewSet and ModelViewSet (Sage Abdullah)WAGTAILADMIN_BASE_URL on "Integrating Wagtail into a Django project" page (Shreshth Srivastava)WAGTAILADMIN_RICH_TEXT_EDITORS setting (Charlie Sue)python3-venv on Ubuntu (Brian Mugo)permission kwarg support in Panels (LB (Ben) Johnston)FieldPanel('title') examples to use the recommended TitleFieldPanel('title') panel (Chinedu Ihedioha)As part of our adoption of Stimulus, in addition to the new documentation, we have migrated several existing components to the framework. Thank you to our core contributor LB who oversees this project, and to all contributors who refactored specific components.
w-bulk Stimulus implementation (LB (Ben) Johnston)w-message controller (LB (Ben) Johnston, Hussain Saherwala)data-tippy HTML attribute usage to the Stimulus data-*-value attributes for w-tooltip & w-dropdown (Subhajit Ghosh, LB (Ben) Johnston)reset method to support Stimulus driven dynamic field resets via the w-action controller (Chiemezuo Akujobi)notify target on the Stimulus dialog for dispatching events internally (Chiemezuo Akujobi)WagtailTestUtils.get_soup() method for testing HTML content (Storm Heg, Sage Abdullah)ViewSet subclasses to customize url_prefix and url_namespace logic (Matt Westcott)SnippetViewSet registration code (Sage Abdullah)IndexView.results_template_name to results.html (Sage Abdullah)stubs.js to prevent Storybook from crashing (LB (Ben) Johnston)slim_header.html template (Sage Abdullah)slim_header.html template to reduce code duplication (Sage Abdullah)imghdr (Jake Howard)imghdr with Willow's built-in MIME type detection (Jake Howard)@total_ordering usage with comparison functions implementation (Virag Jain)<script type="text/django-form-template"><-/script> template approach with HTML template elements in InlinePanel and expanding formset (Mansi Gundre, Subhajit Ghosh, LB (Ben) Johnston)ModelViewSet and SnippetViewSet (Sage Abdullah)lru_cache usage (Jake Howard)date_since in get_most_popular inside search_promotions.models.Query (TopDevPros)classname (not classnames) attributes for all MenuItem usage, including deprecation warnings (LB (Ben) Johnston)classname (not classnames) attribute within the wagtail.images.formats.Format instance, including deprecation warnings (LB (Ben) Johnston)context argument of construct_snippet_listing_buttons hook (Sage Abdullah)search.Query & search.QueryDailyHits model, move final set of templates from the admin search module to the search promotions contrib module (LB (Ben) Johnston)Django 5.0 introduces support for MariaDB's native UUID type on MariaDB 10.7 and above. This breaks backwards compatibility with CHAR-based UUIDs created on earlier versions of Django and MariaDB, and so upgrading a site to Django 5.0+ and MariaDB 10.7+ is liable to result in errors such as Data too long for column 'translation_key' at row 1 or Data too long for column 'uuid' at row 1 when creating or editing pages. To fix this, it is necessary to run the convert_mariadb_uuids management command (available as of Wagtail 5.2.5) after upgrading:
./manage.py convert_mariadb_uuids
This will convert all existing UUID fields used by Wagtail to the new format. New sites created under Django 5.0+ and MariaDB 10.7+ are unaffected.
The legacy moderation system, which was replaced by the new workflow system in Wagtail 2.10, is now deprecated. Since Wagtail 2.10, submitting a page for moderation will use the new workflow system. However, the legacy moderation system is still in place for approving and rejecting pages that were submitted for moderation before Wagtail 2.10.
To view all pages that are still in the legacy moderation system backlog, you can sign in as a superuser and see if there is a "Pages awaiting moderation" section in the admin dashboard. You can approve or reject the pages from there. You can also do this programmatically by querying for Revision.objects.filter(submitted_for_moderation=True) and calling revision.approve_moderation() or revision.reject_moderation() on each revision.
The legacy moderation system will be removed in a future release. If you still have pages in the moderation queue that were submitted for moderation before Wagtail 2.10, you should approve or reject them before upgrading. See for more details.
As a result, the following features are now deprecated:
wagtail.models.Revision.submitted_for_moderationwagtail.models.Revision.submitted_revisionswagtail.models.Revision.approve_moderationwagtail.models.Revision.reject_moderationsubmitted_for_moderation argument in {meth}wagtail.models.RevisionMixin.save_revisionWAGTAIL_MODERATION_ENABLEDwagtail.admin.userbar.ModeratePageItemwagtail.admin.userbar.ApproveModerationEditPageItemwagtail.admin.userbar.RejectModerationEditPageItemwagtail.admin.views.home.PagesForModerationPanelwagtail.admin.views.pages.moderationwagtail.permission_policies.pages.PagePermissionPolicy.revisions_for_moderationIf you use any of the above features, remove them or replace them with the equivalent features from the new workflow system. The above features will be removed in a future release.
classname convention for MenuItem related classes and hooksWagtail MenuItem and menu hooks have been updated to use the more consistent naming of classname (singular) instead of classnames (plural), a convention that started in Wagtail 4.2.
The current classnames keyword argument naming will be supported, but will trigger a deprecation warning. Support for this variant will be removed in a future release.
The following classes will adopt this new convention.
admin.menu.MenuItemadmin.ui.sidebar.ActionMenuItemadmin.ui.sidebar.LinkMenuItemadmin.ui.sidebar.PageExplorerMenuItemcontrib.settings.registry.SettingMenuItemThe following hooks usage may be impacted if classnames were used when generating menu items.
register_admin_menu_itemregister_settings_menu_itemfrom django.urls import reverse
from wagtail import hooks
from wagtail.admin.menu import MenuItem
@hooks.register("register_admin_menu_item")
def register_frank_menu_item():
return MenuItem(
"Frank",
reverse("frank"),
icon_name="folder-inverse",
order=10000,
classname="highlight-menu", # not classnames=...
)
ModelViewSet changed to allow non-integer primary keysTo accommodate models with non-integer primary keys, the URL patterns for the edit and delete views in {class}~wagtail.admin.viewsets.model.ModelViewSet have been changed.
Relative to the viewset's {attr}~wagtail.admin.viewsets.base.ViewSet.url_prefix, the following changes have been made:
<int:pk>/ to edit/<str:pk>/<int:pk>/delete/ to delete/<str:pk>/If you use {func}~django.urls.reverse with {meth}~wagtail.admin.viewsets.base.ViewSet.get_url_name to generate the URLs for these views, no changes are needed. However, if you have hard-coded these URLs in your code, you will need to update them to match the new patterns.
Redirects for the legacy URLs are in place for backwards compatibility, but will be removed in a future release.
The URLs for snippets underwent similar changes in Wagtail 2.14. The redirects for the legacy URLs in {class}~wagtail.snippets.views.snippets.SnippetViewSet have now been marked for removal in a future release.
ModelViewSet automatically registers the model to the reference indexModels that are registered with a ModelViewSet now have reference index tracking enabled by default. This means that you no longer need to call ReferenceIndex.register_model() in your app's ready() method for such models. If this is undesired, you can disable it by setting {attr}~wagtail.admin.viewsets.model.ModelViewSet.add_to_reference_index to False on the ModelViewSet subclass. For more details, see .
IndexView.results_template_name renamed from results.html to index_results.htmlThe IndexView's results_template_name attribute in the GroupViewSet has been renamed from wagtailusers/groups/results.html to wagtailusers/groups/index_results.html for consistency with the other viewsets. If you have customized or extended the template, e.g. for , you will need to rename it to match the new name.
construct_snippet_listing_buttons hook no longer accepts a context argumentThe construct_snippet_listing_buttons hook no longer accepts a context argument. If you have implemented this hook, you will need to remove the context argument from your implementation. If you need to access values computed by the view, you'll need to override the {attr}~wagtail.snippets.views.snippets.SnippetViewSet.index_view_class with a custom IndexView subclass. The get_list_buttons and get_list_more_buttons methods in particular may be overridden to customize the buttons on the listing.
Defining a function for this hook that accepts the context argument will raise a warning, and the function will receive an empty dictionary ({}) as the context. Support for defining the context argument will be completely removed in a future Wagtail release.
page_perms argumentThe arguments passed to the hooks register_page_header_buttons, register_page_listing_buttons, construct_page_listing_buttons and register_page_listing_more_buttons have changed. For all of these hooks, the page_perms argument has been replaced by user; in addition, register_page_header_buttons is now passed a view_name argument, which is either 'edit' or 'index', depending on whether the button is being generated for the page listing or edit view. In summary, the changes are:
register_page_header_buttons: Previously func(page, page_perms, next_url), now func(page, user, next_url, view_name).register_page_listing_buttons: Previously func(page, page_perms, next_url), now func(page, user, next_url).construct_page_listing_buttons: Previously func(buttons, page, page_perms, context), now fn(buttons, page, user, context).register_page_listing_more_buttons: Previously func(page, page_perms, next_url), now func(page, user, next_url).Additionally, the ButtonWithDropdownFromHook constructor, and the resulting hook it creates, should now be passed a user argument instead of page_perms.
Existing code that performs permission checks using page_perms can retrieve the same permission tester object using page.permissions_for_user(user).
Hook functions using the old page_perms signature will continue to work, but this is deprecated and will raise a warning. Support for the old signature will be removed in a future Wagtail release.
If using custom styling for the breadcrumbs, this class has changed from singular to plural for a more intuitive class.
| Old | New |
|---|---|
'w-breadcrumb' |
'w-breadcrumbs' |
slim_header.html templateThe templates for the snippets views have been refactored to reuse the shared slim_header.html template. If you have customized or extended the templates, e.g. for , you will need to update them to match the new structure. As a result, the following templates have been removed:
wagtailsnippets/snippets/headers/_base_header.htmlwagtailsnippets/snippets/headers/create_header.htmlwagtailsnippets/snippets/headers/edit_header.htmlwagtailsnippets/snippets/headers/history_header.htmlwagtailsnippets/snippets/headers/list_header.htmlwagtailsnippets/snippets/headers/usage_header.htmlIn most cases, the usage of those templates can be replaced with the wagtailadmin/shared/headers/slim_header.html template. Refer to the snippets views and templates code for more details.
BaseSidePanels, PageSidePanels and SnippetSidePanels classes are removedThe BaseSidePanels, PageSidePanels and SnippetSidePanels classes that were used to combine the side panels (i.e. status, preview and comments side panels) have been removed. Each side panel is now instantiated directly in the view. The wagtail.admin.ui.components.MediaContainer class can be used to combine the Media objects for the side panels.
The BasePreviewSidePanel, PagePreviewSidePanel and SnippetPreviewSidePanel classes have been replaced with the consolidated PreviewSidePanel class.
The BaseStatusSidePanel class has been renamed to StatusSidePanel.
If you use these classes in your code, you will need to update your code to instantiate the side panels directly in the view.
For example, if you have the following code:
from wagtail.admin.ui.side_panels import PageSidePanels
def my_view(request):
...
side_panels = PageSidePanels(
request,
page.get_latest_revision_as_object(),
show_schedule_publishing_toggle=False,
live_page=page,
scheduled_page=page.get_scheduled_revision_as_object(),
in_explorer=False,
preview_enabled=True,
comments_enabled=False,
)
return render(
request,
template_name,
{"page": page, "side_panels": side_panels, "media": side_panels.media},
)
Update it to the following:
from wagtail.admin.ui.components import MediaContainer
from wagtail.admin.ui.side_panels import PageStatusSidePanel, PreviewSidePanel
def my_view(request):
...
side_panels = [
PageStatusSidePanel(
page,
request,
show_schedule_publishing_toggle=False,
live_object=page,
scheduled_object=page.get_scheduled_revision_as_object(),
locale=page.locale,
translations=translations,
),
PreviewSidePanel(
page,
request,
preview_url=reverse("wagtailadmin_pages:preview_on_edit", args=[page.id]),
),
]
side_panels = MediaContainer(side_panels)
return render(
request,
template_name,
{"page": page, "side_panels": side_panels, "media": side_panels.media},
)
The undocumented JavaScript implementation for the header breadcrumbs component has been migrated to a Stimulus controller and now uses different data attributes.
This may impact custom header implementations that relied on the previous approach, custom breadcrumbs that did not use breadcrumbs and require the expand/collapse behavior may be impacted.
| Old | New |
|---|---|
'wagtail:breadcrumbs-expand' |
'w-breadcrumbs:opened' |
'wagtail:breadcrumbs-collapse' |
'w-breadcrumbs:closed' |
| Old | New |
|---|---|
data-breadcrumb-next |
data-controller="w-breadcrumbs" |
data-toggle-breadcrumbs |
data-w-breadcrumbs-target="toggle" data-action="w-breadcrumbs#toggle mouseenter->w-breadcrumbs#peek" |
data-breadcrumb-item |
data-w-breadcrumbs-target="content" |
Note that the root DOM element also includes a set of additional data attributes to function as the breadcrumbs:
data-controller="w-breadcrumbs"
data-action="keyup.esc@document->w-breadcrumbs#close w-breadcrumbs:open@document->w-breadcrumbs#open w-breadcrumbs:close@document->w-breadcrumbs#close"
data-w-breadcrumbs-close-icon-class="icon-cross"
data-w-breadcrumbs-closed-value="true"
data-w-breadcrumbs-open-icon-class="icon-breadcrumb-expand"
data-w-breadcrumbs-opened-content-class="w-max-w-4xl"
data-w-breadcrumbs-peek-target-value="header"
window.updateFooterSaveWarning global util removedThe undocumented global util window.updateFooterSaveWarning has been removed, this is part of the footer 'unsaved' messages toggling behavior on page forms.
This behavior has now moved to a Stimulus controller and leverages DOM events instead. Calling this function will do nothing and in a future release will throw an error.
You can implement roughly the equivalent functionality with this JavaScript function, however, this will not be guaranteed to work in future releases.
window.updateFooterSaveWarning = (formDirty, commentsDirty) => {
if (!formDirty && !commentsDirty) {
document.dispatchEvent(new CustomEvent('w-unsaved:clear'));
} else {
const [type] = [
formDirty && commentsDirty && 'all',
commentsDirty && 'comments',
formDirty && 'edits',
].filter(Boolean);
document.dispatchEvent(new CustomEvent('w-unsaved:add', { detail: { type } }));
}
};
dropdown template tag argument toggle_tippy_offset renamed to toggle_tooltip_offsetThe naming conventions for tippy related attributes have been updated to align with the generic tooltip naming.
If you are using the undocumented dropdown template tag with the offset arg, this will need to be updated.
| Old | New |
|---|---|
{% dropdown toggle_tippy_offset="[0, -2]" %}...{% enddropdown %} |
{% dropdown toggle_tooltip_offset="[0, -2]" %}...{% enddropdown %} |
escapescript template tag and escape_script functions are deprecatedAs of this release, the undocumented coreutils.escape_script util and escapescript template tag will no longer be supported.
This was used to provide a way for HTML template content in IE11, which is no longer supported, and was non-compliant with CSP support.
The current approach will trigger a deprecation warning and will be removed in a future release.
{% load wagtailadmin_tags %}
<script type="text/django-form-template" id="id_{{ formset.prefix }}-EMPTY_FORM_TEMPLATE">
{% escapescript %}
<div>Widget template content</div>
<script src="/js/my-widget.js"></script>
{% endescapescript %}
</script>
Use the HTML template element to avoid content from being parsed by the browser on load.
<template id="id_{{ formset.prefix }}-EMPTY_FORM_TEMPLATE">
<div>Widget template content</div>
<script src="/js/my-widget.js"></script>
</template>
classname convention within the Image Format instanceWhen using wagtail.images.formats.Format, the created instance set the argument for classes to the attribute classnames (plural), this has now changed to classname (singular).
For any custom code that accessed or modified this undocumented attribute, updates will need to be made as follows.
Accessing self.classnames will still work until a future release, simply returning self.classname, but this will raise a deprecation warning.
# image_formats.py
from django.utils.html import format_html
from wagtail.images.formats import Format, register_image_format
class CustomImageFormat(Format):
def image_to_html(self, image, alt_text, extra_attributes=None):
# contrived example - pull out the class and render on outside element
classname = self.classname # not self.classnames
self.classname = "" # not self.classnames
inner_html = super().image_to_html(image, alt_text, extra_attributes)
return format_html(
"<custom-image class='{}'>{}</custom-image>", classname, inner_html
)
custom_format = CustomImageFormat(
"custom_example", "Custom example", "example-image object-fit", "width-750"
)
register_image_format(custom_format)
search_garbage_collect management command has been removedIn 5.0 the documentation advised that the search_garbage_collect command used to remove old stored search queries and daily hits has been moved to searchpromotions_garbage_collect.
The old command has now been fully removed and if called will throw an error.
Some search promotions URLs and templates have now moved from the main admin search module into the search promotions module.
| Item | Old | New |
|---|---|---|
| URL name | wagtailsearch_admin:queries_chooser |
wagtailsearchpromotions:chooser |
| URL name | wagtailsearch_admin:queries_chooserresults |
wagtailsearchpromotions:queries_chooserresults |
| Template | wagtail/search/templates/wagtailsearch/queries/chooser/chooser.html |
wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/queries/chooser/chooser.html |
| Template | wagtail/search/templates/wagtailsearch/queries/chooser/results.html |
wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/queries/chooser/results.html |
| Template | wagtail/search/templates/wagtailsearch/queries/chooser_field.html |
wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/queries/chooser_field.html |
Block.get_template now accepts a value argumentThe get_template method on StreamField blocks now accepts a value argument in addition to context. Code using the old signature should be updated:
# Old
def get_template(self, context=None): ...
# New
def get_template(self, value=None, context=None): ...
Maintenance: Deprecate legacy URL redirects in ModelViewSet and SnippetViewSet (Sage Abdullah)
wagtailcache & wagtailpagecache (Jake Howard)field.html template (Sage Abdullah)SnippetViewSet menu registration mechanism to base ViewSet class (Sage Abdullah)ModelViewSet (Sage Abdullah)SnippetViewSet template override mechanism to ModelViewSet (Sage Abdullah)SnippetViewSet.list_display to ModelViewSet (Sage Abdullah)wagtail.publish log action on aliases when they are created from live source pages or the source page is published (Dan Braghis)wagtail.unpublish log action on aliases when source page is unpublished (Dan Braghis)IndexView (Sage Abdullah)list_filter, filterset_class, search_fields, search_backend_name, list_export, export_filename, list_per_page, and ordering from SnippetViewSet to ModelViewSet (Sage Abdullah)IndexView and CreateView (Sage Abdullah)IndexView.export_headings via ModelViewSet (Christer Jensen, Sage Abdullah)get_object_list method on ChooserViewSet (Matt Westcott)linked_fields mechanism on chooser widgets to allow choices to be limited by fields on the calling page (Matt Westcott)TableBlock with the mergedCells option (Gareth Palmer)InlinePanel, focus will now shift to that content similar to StreamField (Faishal Manzar)placement in the human_readable_date tooltip template tag (Rohit Sharma)ModelViewSet views (Sage Abdullah){% component %} tag (Matt Westcott)PagesAPIViewSet override default Page model via the model attribute (Neeraj Yetheendran, Herbert Poul)ModelViewSet to be used with models that have non-integer primary keys (Sage Abdullah)HistoryView from snippets and add it to ModelViewSet (Sage Abdullah)UsageView to ModelViewSet (Sage Abdullah)IndexView (Sage Abdullah)wagtail_update_image_renditions management command (Faishal Manzar)hashlib.file_digest if available (Python 3.11+) (Jake Howard)Block.get_template to allow varying template based on value (Florian Delizy)InlinePanel DOM events for when ready and when items added or removed (Faishal Manzar)picture template tag for Django Templates and Jinja (Thibaud Colas)srcset_image template tag for Django Templates and Jinja (Thibaud Colas)Filter instances as input for AbstractImage.get_renditions() (Thibaud Colas)FieldPanel('title') examples to use the recommended TitleFieldPanel('title') panel (Chinedu Ihedioha)purge_revisions management command now respects revisions that have a on_delete=PROTECT foreign key relation and won't delete them (Neeraj P Yetheendran, Meghana Reddy, Sage Abdullah, Storm Heg)FieldBlocks correctly set the required and aria-describedby attributes (Storm Heg)PublishMenuItem to more easily support overriding its label via construct_page_action_menu (Sébastien Corbin)non_fields_errors for any custom form validation (Sébastien Corbin)WAGTAIL_EMAIL_MANAGEMENT_ENABLED setting by not showing 'email' if disabled (Omkar Jadhav)WAGTAILADMIN_BASE_URL on "Integrating Wagtail into a Django project" page (Shreshth Srivastava)WAGTAILADMIN_RICH_TEXT_EDITORS setting (Charlie Sue)python3-venv on Ubuntu (Brian Mugo)WagtailTestUtils.get_soup() method for testing HTML content (Storm Heg, Sage Abdullah)ViewSet subclasses to customise url_prefix and url_namespace logic (Matt Westcott)SnippetViewSet registration code (Sage Abdullah)IndexView.results_template_name to results.html (Sage Abdullah)w-bulk Stimulus implementation (LB (Ben) Johnston)w-message controller (LB (Ben) Johnston, Hussain Saherwala)stubs.js to prevent Storybook from crashing (LB (Ben) Johnston)slim_header.html template (Sage Abdullah)slim_header.html template to reduce code duplication (Sage Abdullah)imghdr (Jake Howard)imghdr with Willow's built-in MIME type detection (Jake Howard)data-tippy HTML attribute usage to the Stimulus data-*-value attributes for w-tooltip & w-dropdown (Subhajit Ghosh, LB (Ben) Johnston)@total_ordering usage with comparison functions implementation (Virag Jain)<script type="text/django-form-template"><-/script> template approach with HTML template elements in InlinePanel and expanding formset (Mansi Gundre, Subhajit Ghosh, LB (Ben) Johnston)ModelViewSet and SnippetViewSet (Sage Abdullah)lru_cache usage (Jake Howard)date_since in get_most_popular inside search_promotions.models.Query (TopDevPros)classname (not classnames) attributes for all MenuItem usage, including deprecation warnings (LB (Ben) Johnston)classname (not classnames) attribute within the wagtail.images.formats.Format instance, including deprecation warnings (LB (Ben) Johnston)context argument of construct_snippet_listing_buttons hook (Sage Abdullah)search.Query & search.QueryDailyHits model, move final set of templates from the admin search module to the search promotions contrib module (LB (Ben) Johnston)InspectView to ModelViewSet (Sage Abdullah)reset method to support Stimulus driven dynamic field resets via the w-action controller (Chiemezuo Akujobi)notify target on the Stimulus dialog for dispatching events internally (Chiemezuo Akujobi)Fix: CVE-2023-45809: Disclosure of user names via admin bulk action views (Matt Westcott)
SnippetBulkAction not respecting models definition (Sandro Rodrigues)October 19, 2023
---
local:
depth: 1
---
This release addresses an information disclosure vulnerability in the Wagtail admin interface. A user with a limited-permission editor account for the Wagtail admin can make a direct URL request to the admin view that handles bulk actions on user accounts. While authentication rules prevent the user from making any changes, the error message discloses the display names of user accounts, and by modifying URL parameters, the user can retrieve the display name for any user. The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin.
Many thanks to quyenheu for reporting this issue. For further details, please see the CVE-2023-45809 security advisory.
SnippetBulkAction not respecting models definition (Sandro Rodrigues)Fix: Avoid use of ignore_conflicts when creating extra permissions for snippets, for SQL Server compatibility (Sage Abdullah)
ignore_conflicts when creating extra permissions for snippets, for SQL Server compatibility (Sage Abdullah)wagtailsearchpromotions_query table is correctly set after migrating data (Jake Howard)None from being exported as strings (Christer Jensen)imghdr with Willow's built-in MIME type detection (Jake Howard)September 25, 2023
---
local:
depth: 1
---
ignore_conflicts when creating extra permissions for snippets, for SQL Server compatibility (Sage Abdullah)wagtailsearchpromotions_query table is correctly set after migrating data (Jake Howard)None from being exported as strings (Christer Jensen)imghdr with Willow's built-in MIME type detection (Jake Howard)AutocompleteField for full functionalityIn Wagtail 4.2, the search bar within snippet chooser interfaces (and custom choosers created via ChooserViewSet) returned results for partial word matches - for example, a search for "wagt" would return results containing "Wagtail" - if this was supported by the search backend in use, and at least one AutocompleteField was present in the model's search_fields definition. Otherwise, it would fall back to only matching on complete words. In Wagtail 5.0, this fallback behavior was removed, and consequently a model with no AutocompleteFields in place would return no results.
As of Wagtail 5.1.2, the fallback behavior has been restored. Nevertheless, it is strongly recommended that you add AutocompleteField to your models' search_fields definitions, to ensure that users can receive search results continuously as they type. For example:
from wagtail.search import index
# ... other imports
@register_snippet
class MySnippet(index.Indexed, models.Model):
search_fields = [
index.SearchField("name"),
index.AutocompleteField("name"),
]
Introduce wagtail.admin.ui.tables.BooleanColumn to display boolean values as icons (Sage Abdullah)
wagtail.admin.ui.tables.BooleanColumn to display boolean values as icons (Sage Abdullah)None falsy values instead of blank in generic table cell template (Sage Abdullah)read_only panels for fields with translatable choice labels (Florent Lebreton)August 14, 2023
---
local:
depth: 1
---
wagtail.admin.ui.tables.BooleanColumn to display boolean values as icons (Sage Abdullah)None falsy values instead of blank in generic table cell template (Sage Abdullah)read_only panels for fields with translatable choice labels (Florent Lebreton)Maintenance: Deprecate insert_editor_css in favour of insert_global_admin_css (Ester Beltrami)
md5 as not being used for secure purposes, to avoid flagging on FIPS-mode systems (Sean Kelly)parse_query_string as a QueryDict to support multiple values (Aman Pandey)MenuItem.name for all admin menu and submenu items (Justin Koestinger)PagePermissionPolicy (Sage Abdullah)UserPagePermissionsProxy and PagePermissionTester to use PagePermissionPolicy (Sage Abdullah, Tidiane Dia)AbstractImage.get_renditions() for efficient generation of multiple renditions (Andy Babic)StreamField block when only one block type is declared (Sébastien Corbin)SnippetViewSet.list_export (Sage Abdullah)attrs on FieldPanel, FieldRowPanel, MultiFieldPanel, and others (Aman Pandey, Antoni Martyniuk, LB (Ben) Johnston)--template option to wagtail start (Thibaud Colas)purge_revisions command (Sage Abdullah)parent_page_types would disallow it (Dan Braghis)UsageView from EditView for snippets (Christer Jensen)RichText objects with the same values compare as equal (NikilTn)gettext_lazy on generic model views so that language settings are correctly used (Matt Westcott)MultipleChooserPanel (Matt Westcott)innerHTML when modifying DOM content (LB (Ben) Johnston)ValueError when extending PagesAPIViewSet and setting meta_fields to an empty list (Henry Harutyunyan, Alex Morega)PagePermissionHelper.user_can_unpublish_obj() in ModelAdmin (Sébastien Corbin)search_promotions 0004_copy_queries migration for long-lived Wagtail instances (Sage Abdullah)TypeError in 0088_fix_log_entry_json_timestamps migration (Sage Abdullah)page_header_buttons template tag when accessing the context's request object (Robert Rollins)ModelAdminGroup (Onno Timmerman)log_action parameter on RevisionMixin.save_revision (Christer Jensen)searchpromotions (Scott Foster)insert_editor_css in favour of insert_global_admin_css (Ester Beltrami)specific on Task and TaskState (Matt Westcott)parent_context is mutable (Andreas Nüßlein)UserPagePermissionsProxy (Sage Abdullah)django-filter version upper bound to v24 (Yuekui)w-swap, a Stimulus controller (LB (Ben) Johnston)w-tooltip Stimulus controller (LB (Ben) Johnston)jest-environment-jsdom and new snapshot format (LB (Ben) Johnston)w-dialog Stimulus controller (Loveth Omokaro, LB (Ben) Johnston)w-teleport Stimulus controller (Loveth Omokaro, LB (Ben) Johnston)"wagtailadmin/shared/field_as_li.html" template include (Storm Heg)wagtail.contrib.modeladmin (Sage Abdullah)sphinx_wagtail_theme to v6.1.1 which includes multiple styling fixes and always visible code copy buttons (LB (Ben) Johnston)August 1, 2023
---
local:
depth: 1
---
FieldPanels can now be marked as read-only with the read_only=True keyword argument, so that they are displayed in the admin but cannot be edited. This feature was developed by Andy Babic.
As part of Google Season of Docs 2023, we worked with technical writer Damilola Oladele to make improvements to Wagtail’s "Getting started" tutorial. Here are the specific changes made as part of this project:
Thank you to Damilola for his work, and to Google for sponsoring this project.
wagtail startThe wagtail start command now supports an optional --template argument that allows you to specify a custom project template to use. This is useful if you want to use a custom template that includes additional features or customizations. For more details, see the project template reference. This feature was developed by Thibaud Colas.
The boost option on SearchField, to increase the ranking of search results that match on the specified field, is now respected by Elasticsearch 6 and above. This was previously only supported up to Elasticsearch 5, due to a change in Elasticsearch's API. This feature was developed by Shohan Dutta Roy.
This release adds support for Elasticsearch 8. This can be set up by installing a version 8.x release of the elasticsearch Python package, and setting wagtail.search.backends.elasticsearch8 as the search backend. Compatibility updates were contributed by Matt Westcott and Wesley van Lee.
As part of tackling Wagtail’s technical debt and improving CSP compatibility, we have continued extending our usage of Stimulus, based on the plans laid out in RFC 78: Adopt Stimulus.
attrs on FieldPanel and other panels to aid in custom Stimulus usage (Aman Pandey, Antoni Martyniuk, LB (Ben) Johnston)w-swap, a Stimulus controller (LB (Ben) Johnston)w-tooltip Stimulus controller (LB (Ben) Johnston)w-dialog Stimulus controller (Loveth Omokaro, LB (Ben) Johnston)w-teleport Stimulus controller (Loveth Omokaro, LB (Ben) Johnston)Wagtail now supports AVIF, a modern image format. We encourage all site implementers to consider using it to improve the performance of the sites and reduce their carbon footprint. For further details, see image file format, output image format and image quality.
This feature was developed by Aman Pandey as part of the Google Summer of Code program and a partnership with the Green Web Foundation and Green Coding Berlin, with support from Dan Braghis, Thibaud Colas, Sage Abdullah, Arne Tarara (Green Coding Berlin), and Chris Adams (Green Web Foundation).
This release includes several changes to permissions, to make them easier to use and maintain, as well as to improve performance.
PagePermissionPolicy (Sage Abdullah)UserPagePermissionsProxy and PagePermissionTester to use PagePermissionPolicy (Sage Abdullah, Tidiane Dia)UserPagePermissionsProxy (Sage Abdullah)We have made several improvements to snippets as part of RFC 85: Snippets parity with ModelAdmin, ahead of the deprecation of ModelAdmin contrib app.
SnippetViewSet.list_export (Sage Abdullah)purge_revisions command (Sage Abdullah)md5 as not being used for secure purposes, to avoid flagging on FIPS-mode systems (Sean Kelly)parse_query_string as a QueryDict to support multiple values (Aman Pandey)MenuItem.name for all admin menu and submenu items (Justin Koestinger)AbstractImage.get_renditions() for efficient generation of multiple renditions (Andy Babic)href="tel:..." attribute (Sahil Jangra)StreamField block when only one block type is declared (Sébastien Corbin)attrs on FieldPanel, FieldRowPanel, MultiFieldPanel, and others (Aman Pandey, Antoni Martyniuk, LB (Ben) Johnston)parent_page_types would disallow it (Dan Braghis)UsageView from EditView for snippets (Christer Jensen)RichText objects with the same values compare as equal (NikilTn)gettext_lazy on generic model views so that language settings are correctly used (Matt Westcott)MultipleChooserPanel (Matt Westcott)gettext_lazy works correctly when using verbose_name on a generic Settings models (Sébastien Corbin)innerHTML when modifying DOM content (LB (Ben) Johnston)ValueError when extending PagesAPIViewSet and setting meta_fields to an empty list (Henry Harutyunyan, Alex Morega)PagePermissionHelper.user_can_unpublish_obj() in ModelAdmin (Sébastien Corbin)search_promotions 0004_copy_queries migration for long-lived Wagtail instances (Sage Abdullah)TypeError in 0088_fix_log_entry_json_timestamps migration (Sage Abdullah)page_header_buttons template tag when accessing the context's request object (Robert Rollins)ModelAdminGroup (Onno Timmerman)log_action parameter on RevisionMixin.save_revision (Christer Jensen)searchpromotions (Scott Foster)insert_editor_css in favour of insert_global_admin_css (Ester Beltrami)specific on Task and TaskState (Matt Westcott)parent_context is mutable (Andreas Nüßlein)CONTRIBUTORS file to Markdown (Dan Braghis)django-filter version upper bound to v23 (Yuekui)jest-environment-jsdom and new snapshot format (LB (Ben) Johnston)"wagtailadmin/shared/field_as_li.html" template include (Storm Heg)sphinx_wagtail_theme to v6.1.1 which includes multiple styling fixes and always visible code copy buttons (LB (Ben) Johnston)AutocompleteField for full functionalityIn Wagtail 4.2, the search bar within snippet chooser interfaces (and custom choosers created via ChooserViewSet) returned results for partial word matches - for example, a search for "wagt" would return results containing "Wagtail" - if this was supported by the search backend in use, and at least one AutocompleteField was present in the model's search_fields definition. Otherwise, it would fall back to only matching on complete words. In Wagtail 5.0, this fallback behavior was removed, and consequently a model with no AutocompleteFields in place would return no results.
As of Wagtail 5.1.2, the fallback behavior has been restored. Nevertheless, it is strongly recommended that you add AutocompleteField to your models' search_fields definitions, to ensure that users can receive search results continuously as they type. For example:
from wagtail.search import index
# ... other imports
@register_snippet
class MySnippet(index.Indexed, models.Model):
search_fields = [
index.SearchField("name"),
index.AutocompleteField("name"),
]
GroupPagePermission now uses Django's Permission modelThe GroupPagePermission model that is responsible for assigning page permissions to groups now uses Django's Permission model instead of a custom string. This means that the permission_type CharField has been deprecated and replaced with a permission ForeignKey to the Permission model.
In addition to this, "edit" permissions now use the term change within the code. As a result, GroupPagePermissions that were previously recorded with permission_type="edit" are now recorded with a Permission object that has the codename="change_page" and a content_type that points to the Page model. Any permission checks that are done using PagePermissionPolicy should also use change instead of edit.
If you have any fixtures for the GroupPagePermission model, you will need to update them to use the new Permission model. For example, if you have a fixture that looks like this:
{
"pk": 11,
"model": "wagtailcore.grouppagepermission",
"fields": {
"group": ["Event moderators"],
"page": 12,
"permission_type": "edit"
}
}
Update it to use a natural key for the permission field instead of the permission_type field:
{
"pk": 11,
"model": "wagtailcore.grouppagepermission",
"fields": {
"group": ["Event moderators"],
"page": 12,
"permission": ["change_page", "wagtailcore", "page"]
}
}
If you have any code that creates GroupPagePermission objects, you will need to update it to use the Permission model instead of the permission_type string. For example, if you have code that looks like this:
from wagtail.models import GroupPagePermission
permission = GroupPagePermission(group=group, page=page, permission_type="edit")
permission.save()
Update it to use the Permission model instead:
from django.contrib.auth.models import Permission
from wagtail.models import GroupPagePermission
permission = GroupPagePermission(
group=group,
page=page,
permission=Permission.objects.get(
content_type__app_label="wagtailcore", codename="change_page"
),
)
permission.save()
During the deprecation period, the permission_type field will still be available on the GroupPagePermission model and is used to automatically populate empty permission field as part of a system check. The permission_type field will be removed in Wagtail 6.0.
The ordering for "Object permissions" and "Other permissions" now follows a predictable order equivalent to Django's default Model ordering.
This will be different to the previous indeterminate ordering.
The default ordering is now ["content_type__app_label", "content_type__model"]. See for details on how to customize this order.
ModelLogEntry and PageLogEntry are now ISO-formatted and UTCPreviously, timestamps stored in the "data"-JSONField of ModelLogEntry and PageLogEntry have used the custom python format %d %b %Y %H:%M. Additionally, the "go_live_at" timestamp had been stored with the configured local timezone, instead of UTC.
This has now been fixed, all timestamps are now stored as UTC, and because the "data"-JSONField now uses Django's DjangoJSONEncoder, those datetime objects are now automatically converted to the ISO format. This release contains a new migration 0088_fix_log_entry_json_timestamps which converts all existing timestamps used by Wagtail to the new format.
If you've developed your own subclasses of ModelLogEntry, PageLogEntry or BaseLogEntry, or used those existing models to create custom log entries, and you've stored timestamps similarly to Wagtail's old implementation (using strftime("%d %b %Y %H:%M")). You may want to adapt the storage of those timestamps to a consistent format too.
There are probably three places in your code, which have to be changed:
strftime("%d %b %Y %H:%M"), you can now store the datetime directly in the "data" field. We've implemented a new helper wagtail.utils.timestamps.ensure_utc(), which ensures the correct timezone (UTC).LogFormatter, we've created utils to parse (wagtail.utils.timestamps.parse_datetime_localized()) and render (wagtail.utils.timestamps.render_timestamp()) those timestamps. Look at the existing formatters here.Wagtail will try to use the cache called "renditions". If no such cache exists, it will fall back to using the default cache. You can configure the "renditions" cache to use a different cache backend or to provide additional configuration parameters.
Python 3.7 is no longer supported as of this release; please upgrade to Python 3.8 or above before upgrading Wagtail.
Wagtail no longer supports Pillow versions below 9.1.0.
The Elasticsearch 5 and 6 search backends are deprecated and will be removed in a future release; please upgrade to Elasticsearch 7 or above.
insert_editor_css hook is deprecatedThe insert_editor_css hook has been deprecated. The insert_global_admin_css hook has the same functionality, and all uses of insert_editor_css should be changed to insert_global_admin_css.
wagtail.contrib.modeladmin is deprecatedAs part of the RFC 85: Snippets parity with ModelAdmin implementation, the wagtail.contrib.modeladmin app is deprecated. To manage non-page models in Wagtail, use wagtail.snippets instead.
If you still rely on ModelAdmin, use the separate wagtail-modeladmin package. The wagtail.contrib.modeladmin module will be removed in a future release.
UserPagePermissionsProxy is deprecatedThe undocumented wagtail.models.UserPagePermissionsProxy class is deprecated.
If you use the .for_page(page) method of the class to get a PagePermissionTester instance, you can replace it with page.permissions_for_user(user).
If you use the other methods, they can be replaced via the wagtail.permission_policies.pages.PagePermissionPolicy class. The following is a list of the PagePermissionPolicy equivalent of each method:
from wagtail.models import UserPagePermissionsProxy
from wagtail.permission_policies.pages import PagePermissionPolicy
# proxy = UserPagePermissionsProxy(user)
permission_policy = PagePermissionPolicy()
# proxy.revisions_for_moderation()
permission_policy.revisions_for_moderation(user)
# proxy.explorable_pages()
permission_policy.explorable_instances(user)
# proxy.editable_pages()
permission_policy.instances_user_has_permission_for(user, "change")
# proxy.can_edit_pages()
permission_policy.instances_user_has_permission_for(user, "change").exists()
# proxy.publishable_pages()
permission_policy.instances_user_has_permission_for(user, "publish")
# proxy.can_publish_pages()
permission_policy.instances_user_has_permission_for(user, "publish").exists()
# proxy.can_remove_locks()
permission_policy.user_has_permission(user, "unlock")
The UserPagePermissionsProxy object that is available in page's ActionMenuItem context as user_page_permissions (which might be used as part of a register_page_action_menu_item hook) has been deprecated. In cases where the page object is available (e.g. the page edit view), the PagePermissionTester object stored as the user_page_permissions_tester context variable can still be used.
The UserPagePermissionsProxy object that is available in the template context as user_page_permissions as a side-effect of the page_permissions template tag has also been deprecated.
If you use the user_page_permissions context variable or use the UserPagePermissionsProxy class directly, make sure to replace it either with the PagePermissionTester or the PagePermissionPolicy equivalent.
get_pages_with_direct_explore_permission, get_explorable_root_page, and users_with_page_permission are deprecatedThe undocumented get_pages_with_direct_explore_permission and get_explorable_root_page functions in wagtail.admin.navigation are deprecated. They can be replaced with PagePermissionPolicy().instances_with_direct_explore_permission(user) and PagePermissionPolicy().explorable_root_instance(user), respectively.
The undocumented users_with_page_permission function in wagtail.admin.auth is also deprecated. It can be replaced with PagePermissionPolicy().users_with_permission_for_instance(action, page, include_superusers).
wagtailadmin/shared/last_updated.html is no longer availableThe undocumented shared include wagtailadmin/shared/last_updated.html is no longer available as it used the legacy Bootstrap tooltips and was not accessible. If you need to achieve a similar output, an element that shows a simple date with a tooltip for the full date, use the human_readable_date template tag instead.
{% include "wagtailadmin/shared/last_updated.html" with last_updated=my_model.timestamp %}
{% load wagtailadmin_tags %}
<!-- ... -->
{% human_readable_date my_model.timestamp %}
field_as_li.html will be removedThe documented include "wagtailadmin/shared/field_as_li.html" will be removed in a future release, if being used it will need to be replaced with "wagtailadmin/shared/field.html" wrapped within li tags.
{% include "wagtailadmin/shared/field_as_li.html" %}
<li>
{% include "wagtailadmin/shared/field.html" %}
</li>
The AdminTagWidget widget has now been migrated to a Stimulus controller, if using this widget in Python, no changes are needed to adopt the new approach.
If the widget is being instantiated in JavaScript or HTML with the global util window.initTagField, this undocumented util should be replaced with the new data-* attributes approach. Additionally, any direct usage of the jQuery widget in JavaScript (e.g. $('#my-element).tagit()) should be removed.
The global util will be removed in a future release. It is recommended that the documented AdminTagWidget be used. However, if you need to use the JavaScript approach you can do this with the following example.
<input id="id_tags" type="text" value="popular, technology" hidden />
<script>
window.initTagField('id_tags', 'path/to/url', { autocompleteOnly: true });
</script>
<input
id="id_tags"
type="text"
value="popular, technology"
hidden
data-controller="w-tag"
data-w-tag-options-value='{"autocompleteOnly": true}'
data-w-tag-url-value="/path/to/url"
/>
Note: The data-w-tag-options-value is a JSON object serialized into string. Django's HTML escaping will handle it automatically when you use the AdminTagWidget, but if you are manually writing the attributes, be sure to use quotation marks correctly.
Previously the header search relied on inline scripts and a window.headerSearch global to activate the behavior. This has now changed to a data attributes approach and the window global usage will be removed in a future major release.
If you are using the documented Wagtail viewsets, Snippets or ModelAdmin approaches to building custom admin views, there should be no change required.
If you are using the shared header template include for a custom search integration, here's how to adopt the new approach.
{% extends "wagtailadmin/base.html" %}
{% load wagtailadmin_tags %}
{% block extra_js %}
{{ block.super }}
<script>
window.headerSearch = {
url: "{% url 'myapp:search_results' %}",
termInput: '#id_q',
targetOutput: '#my-results',
};
</script>
{% endblock %}
{% block content %}
{% include "wagtailadmin/shared/header.html" with title="my title" search_url="myapp:index" %}
... other content
{% endblock %}
Note: No need for extra_js usage at all.
{% extends "wagtailadmin/base.html" %}
{% load wagtailadmin_tags %}
{% block content %}
{% url 'myapp:search_results' as search_results_url %}
{% include "wagtailadmin/shared/header.html" with title="my title" search_url="myapp:index" search_results_url=search_results_url search_target="#my-results" %}
... other content
{% endblock %}
Alternatively, if you have customizations that manually declare or override window.headerSearch, here's how to adopt the new approach.
<script>
window.headerSearch = {
url: '{{ my_async_results_url }}',
termInput: '#id_q',
targetOutput: '#some-results',
};
</script>
<form role="search">
<input type="text" name="q" id="id_q" />
</form>
<div id="some-results"></div>
<form
role="search"
data-controller="w-swap"
data-action="change->w-swap#searchLazy input->w-swap#searchLazy"
data-w-swap-src-value="{{ my_async_results_url }}"
data-w-swap-target-value="#some-results"
>
<input type="text" name="q" id="id_q" data-w-swap-target="input" />
</form>
<div id="some-results"></div>
The undocumented Bootstrap jQuery tooltip widget is no longer in use, you will need to update any HTML that is using these attributes to the new syntax.
<!-- Old attributes: -->
<span data-wagtail-tooltip="Tooltip content here">Label</span>
<!-- New attributes: -->
<span data-controller="w-tooltip" data-w-tooltip-content-value="Tooltip content here">Label</span>
The undocumented client-side Custom Event handling for dialog showing & hiding will change in a future release.
| Action | Old event | New event |
|---|---|---|
| Show | wagtail:show |
w-dialog:show |
| Hide | wagtail:hide |
w-dialog:hide |
Additionally, two new events will be dispatched when the dialog visibility changes.
| Action | Event name |
|---|---|
| Show | w-dialog:shown |
| Hide | w-dialog:hidden |
.../tables/attrs.html has been renamed to .../shared/attrs.htmlThe undocumented shared template for rendering a dict of attrs to HTML, similar to Django form widgets, has been renamed.
| Template location | Usage with include |
|
|---|---|---|
| Old | wagtail/admin/templates/wagtailadmin/tables/attrs.html |
{% include "wagtailadmin/tables/attrs.html" with attrs=link_attrs %} |
| New | wagtail/admin/templates/wagtailadmin/shared/attrs.html |
{% include "wagtailadmin/shared/attrs.html" with attrs=link_attrs %} |
Maintenance: Deprecate insert_editor_css in favour of insert_global_admin_css (Ester Beltrami)
md5 as not being used for secure purposes, to avoid flagging on FIPS-mode systems (Sean Kelly)parse_query_string as a QueryDict to support multiple values (Aman Pandey)MenuItem.name for all admin menu and submenu items (Justin Koestinger)PagePermissionPolicy (Sage Abdullah)UserPagePermissionsProxy and PagePermissionTester to use PagePermissionPolicy (Sage Abdullah, Tidiane Dia)AbstractImage.get_renditions() for efficient generation of multiple renditions (Andy Babic)StreamField block when only one block type is declared (Sébastien Corbin)SnippetViewSet.list_export (Sage Abdullah)attrs on FieldPanel, FieldRowPanel, MultiFieldPanel, and others (Aman Pandey, Antoni Martyniuk, LB (Ben) Johnston)--template option to wagtail start (Thibaud Colas)purge_revisions command (Sage Abdullah)parent_page_types would disallow it (Dan Braghis)UsageView from EditView for snippets (Christer Jensen)RichText objects with the same values compare as equal (NikilTn)gettext_lazy on generic model views so that language settings are correctly used (Matt Westcott)MultipleChooserPanel (Matt Westcott)innerHTML when modifying DOM content (LB (Ben) Johnston)ValueError when extending PagesAPIViewSet and setting meta_fields to an empty list (Henry Harutyunyan, Alex Morega)PagePermissionHelper.user_can_unpublish_obj() in ModelAdmin (Sébastien Corbin)ModelAdminGroup (Onno Timmerman)log_action parameter on RevisionMixin.save_revision (Christer Jensen)searchpromotions (Scott Foster)insert_editor_css in favour of insert_global_admin_css (Ester Beltrami)specific on Task and TaskState (Matt Westcott)parent_context is mutable (Andreas Nüßlein)UserPagePermissionsProxy (Sage Abdullah)django-filter version upper bound to v24 (Yuekui)w-swap, a Stimulus controller (LB (Ben) Johnston)w-tooltip Stimulus controller (LB (Ben) Johnston)jest-environment-jsdom and new snapshot format (LB (Ben) Johnston)w-dialog Stimulus controller (Loveth Omokaro, LB (Ben) Johnston)w-teleport Stimulus controller (Loveth Omokaro, LB (Ben) Johnston)"wagtailadmin/shared/field_as_li.html" template include (Storm Heg)wagtail.contrib.modeladmin (Sage Abdullah)Fix: CVE-2023-45809: Disclosure of user names via admin bulk action views (Matt Westcott)
October 19, 2023
---
local:
depth: 1
---
This release addresses an information disclosure vulnerability in the Wagtail admin interface. A user with a limited-permission editor account for the Wagtail admin can make a direct URL request to the admin view that handles bulk actions on user accounts. While authentication rules prevent the user from making any changes, the error message discloses the display names of user accounts, and by modifying URL parameters, the user can retrieve the display name for any user. The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin.
Many thanks to quyenheu for reporting this issue. For further details, please see the CVE-2023-45809 security advisory.
Maintenance: Relax Willow / Pillow dependency to allow use of current Pillow versions with security fixes (Dan Braghis)
October 4, 2023
---
local:
depth: 1
---
Fix: Avoid use of ignore_conflicts when creating extra permissions for snippets, for SQL Server compatibility (Sage Abdullah)
ignore_conflicts when creating extra permissions for snippets, for SQL Server compatibility (Sage Abdullah)wagtailsearchpromotions_query table is correctly set after migrating data (Jake Howard)September 25, 2023
---
local:
depth: 1
---
ignore_conflicts when creating extra permissions for snippets, for SQL Server compatibility (Sage Abdullah)wagtailsearchpromotions_query table is correctly set after migrating data (Jake Howard)Added TitleFieldPanel to support title / slug field synchronisation (LB (Ben) Johnston)
TitleFieldPanel to support title / slug field synchronisation (LB (Ben) Johnston)MultipleChooserPanel (Matt Westcott)June 21, 2023
---
local:
depth: 1
---
MultipleChooserPanel (Matt Westcott)TitleFieldPanel for the page title fieldThis release introduces a new class, which is used by default for the page title field and provides the mechanism for synchronizing the slug field with the title. Before Wagtail 5.0, this happened automatically on any field named 'title'.
If you have used FieldPanel("title") directly in a panel definition (rather than extending Page.content_panels as standard), and wish to restore the previous behavior of auto-populating the slug, you will need to change this to TitleFieldPanel("title"). For example:
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
# ...
content_panels = [
MultiFieldPanel([
FieldPanel("title"),
FieldPanel("subtitle"),
]),
]
should become:
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, TitleFieldPanel
# ...
content_panels = [
MultiFieldPanel([
TitleFieldPanel("title"),
FieldPanel("subtitle"),
]),
]
Fix: Rectify previous fix for TableBlock becoming uneditable after save (Sage Abdullah)
WAGTAILADMIN_COMMENTS_ENABLED (Thibaud Colas)for_update value for get_form_class in SnippetViewSet edit views (Sage Abdullah)UsageView from EditView for snippets (Christer Jensen)log_action parameter on RevisionMixin.save_revision (Christer Jensen)May 25, 2023
---
local:
depth: 1
---
WAGTAILADMIN_COMMENTS_ENABLED (Thibaud Colas)for_update value for get_form_class in SnippetViewSet edit views (Sage Abdullah)UsageView from EditView for snippets (Christer Jensen)log_action parameter on RevisionMixin.save_revision (Christer Jensen)Maintenance: Removed features deprecated in Wagtail 3.0 and 4.0 (Matt Westcott)
WAGTAILIMAGES_EXTENSIONS setting to restrict image uploads to specific file types (Aman Pandey, Ananjan-R)Access level to be easier to understand (Vallabh Tiwari).button-longrunning behaviour to a Stimulus controller with support for custom label element & duration (Loveth Omokaro)change event (George Sakkis)search_fields = [] (Daniel Kirkham)wagtail.search.utils.parse_query_string to allow inner single quotes for key/value parsing (Aman Pandey)Locale for more convenient usage within templates (Andy Babic)SnippetViewSet.icon (Daniel Kirkham, Sage Abdullah)MenuItem.name for Snippets, Reports, and Settings menu items (Sage Abdullah)list_filter attribute (Sage Abdullah)IndexView (Sage Abdullah)search_fields and search backend via SnippetViewSet (Sage Abdullah)panels / edit_handler to be specified via SnippetViewSet (Sage Abdullah)label_format on StructBlock gracefully handles missing variables (Aadi jindal)Site.get_site_root_paths works on cache backends that do not preserve Python objects (Jaap Roes)StructValue copies (Tidiane Dia)GroupApprovalTask if it's locked by someone outside of the group (Sage Abdullah)WorkflowLock is currently applied (Sage Abdullah)wagtail.schedule.cancel (Stefan Hammer)require_admin_access() (Stefan Hammer)radio input fields (Mehul Aggarwal)TemplateResponses for users with a custom timezone (Stefan Hammer, Sage Abdullah)download_url when WAGTAILDOCS_SERVE_METHOD is direct (Swojak-A)ClusterableModel requirements for using relations with RevisionMixin-enabled models (Sage Abdullah)strictPropertyInitialization in tsconfig (Thibaud Colas)Page.get_static_site_paths method (Yosr Karoui)CollapseAll and MinimapItem components (Albina Starykova)AutoFieldController to the less confusing SubmitController (Loveth Omokaro)script tags with template tag for image/document bulk uploads (Rishabh Kumar Bahukhandi)SlugInput widget (Loveth Omokaro)status HTML usage to shared template tag (Aman Pandey, LB (Ben) Johnston, Himanshu Garg)ModelAdmin and Snippets type index header (Aman Pandey)wagtailsearch.Query to wagtail.contrib.search_promotions (Karl Hobley)initErrorDetection (tabs error counts) to a Stimulus Controller w-count (Aman Pandey)window.addMessage behaviour to a global event listener & Stimulus Controller approach with w-messages (Aman Pandey)SnippetViewSet.on_register() (Sage Abdullah)pageurl template tag (Satvik Vashisht)window.initSlugAutoPopulate behaviour to a Stimulus Controller w-sync (Loveth Omokaro)status classes to w-status to align with preferred CSS class naming conventions (Mansi Gundre)wagtail.test.utils to avoid cross-dependency issues (Matt Westcott)w-bulk, remove inline script usage (Hanoon)SnippetViewSet to extend ModelViewSet (Sage Abdullah)w-disimissible (Loveth Omokaro)w-autosize controller using autosize npm package v6 (Suyash Srivastava)w-action controller to support a click method (Suyash Srivastava)w-action controller usage (Aadi jindal, LB (Ben) Johnston)May 2, 2023
---
local:
depth: 1
---
This release adds support for Django 4.2.
On deleting a page, image, document or snippet, the confirmation screen now provides a summary of where the object is used, allowing users to see the effect that deletion will have elsewhere on the site. This also prevents objects from being deleted in cases where deletion would be blocked by an on_delete=PROTECT constraint. This feature was developed by Sage Abdullah.
The image library can now be configured to allow uploading SVG images. These are handled by the {% image %} template tag as normal, with some limitations on image operations - for full details, see . This feature was developed by Joshua Munn, and sponsored by YouGov.
Support for adding custom validation logic to StreamField blocks has been formalized and simplified. For most purposes, raising a ValidationError from the block's clean method is now sufficient; more complex behaviors (such as attaching errors to a specific child block) are possible through block-specific subclasses of ValidationError. For more details, see . This feature was developed by Matt Westcott.
Wagtail’s icon set is now fully updated, customizable, and extendable. Built-in icons are now based on the latest FontAwesome visuals, with capabilities to both customize existing icons as well as add new ones. In particular, this includes:
{% icon %} icon template tag to reuse icons in custom templates.register_icons hook to register new icons and override existing ones.SnippetViewSet.icon.For more details, see our new icons documentation.
This has been made possible thanks to a multi-year refactoring effort to migrate all icons to SVG. Thank you to all contributors who participated in this effort: Coen van der Kamp, LB (Ben) Johnston, Dan Braghis, Daniel Kirkham, Sage Abdullah, Thibaud Colas, Scott Cranfill, Storm Heg, Steve Steinwand, Jérôme Lebleu, Abayomi Victory.
The built-in accessibility checker has been updated with:
~wagtail.admin.userbar.ContentCheckerItem for simpler customization of the checks performed.Those improvements were implemented by Albina Starykova as part of an Outreachy internship, with support from mentors Thibaud Colas, Sage Abdullah, and Joshua Munn.
Following its introduction in Wagtail 4.1, we have made several improvements to the page editor minimap:
Thank you to everyone who provided feedback on this new addition to the editor experience. Those changes were implemented by Thibaud Colas.
Wagtail’s admin interface now supports dark mode. The new dark theme can be enabled in account preferences, as well as configuring permanent usage of the light theme, or following system preferences.
We hope this new theme will bring accessibility improvements for users who prefer light text on dark backgrounds, and energy usage efficiency improvements for users of OLED monitors. This feature was developed by Thibaud Colas, with designs from Ben Enright.
Continuing on recent improvements to snippets, we have made the following additions to how snippets can be customized in the admin interface:
IndexView.search_fields and search backend via SnippetViewSet.list_filter attribute.panels / edit_handler to be specified via SnippetViewSet.SnippetViewSet.icon.Developed by Sage Abdullah, these features were implemented as part of RFC 85: Snippets parity with ModelAdmin. We will start the deprecation process of the ModelAdmin contrib package in the next feature release and publish it as a separate package for users who wish to continue using it. The ModelAdmin package will be removed in Wagtail 6.0.
WAGTAILIMAGES_EXTENSIONS setting to restrict image uploads to specific file types (Aman Pandey, Ananjan-R)Access level to be easier to understand (Vallabh Tiwari).button-longrunning behavior to a Stimulus controller with support for custom label element & duration (Loveth Omokaro)change event (George Sakkis)search_fields = [] (Daniel Kirkham)wagtail.search.utils.parse_query_string to allow inner single quotes for key/value parsing (Aman Pandey)Locale for more convenient usage within templates, see (Andy Babic)MenuItem.name for Snippets, Reports, and Settings menu items (Sage Abdullah)label_format on StructBlock gracefully handles missing variables (Aadi jindal)Site.get_site_root_paths works on cache backends that do not preserve Python objects (Jaap Roes)GroupApprovalTask if it's locked by someone outside of the group (Sage Abdullah)WorkflowLock is currently applied (Sage Abdullah)wagtail.schedule.cancel (Stefan Hammer)require_admin_access() (Stefan Hammer)radio input fields (Mehul Aggarwal)TemplateResponses for users with a custom timezone (Stefan Hammer, Sage Abdullah)download_url when WAGTAILDOCS_SERVE_METHOD is direct (Swojak-A)SettingsPanel reference in the page editing TabbedInterface example as SettingsPanel no longer shows anything as of 4.1 (Kenny Wolf, Julian Bigler)ClusterableModel requirements for using relations with RevisionMixin-enabled models (Sage Abdullah)strictPropertyInitialization in tsconfig (Thibaud Colas)Page.get_static_site_paths method (Yosr Karoui)CollapseAll and MinimapItem components (Albina Starykova)AutoFieldController to the less confusing SubmitController (Loveth Omokaro)script tags with template tag for image/document bulk uploads (Rishabh Kumar Bahukhandi)SlugInput widget (Loveth Omokaro)status HTML usage to shared template tag (Aman Pandey, LB (Ben) Johnston, Himanshu Garg)ModelAdmin and Snippets type index header (Aman Pandey)wagtailsearch.Query to wagtail.contrib.search_promotions (Karl Hobley)initErrorDetection (tabs error counts) to a Stimulus Controller w-count (Aman Pandey)window.addMessage behavior to a global event listener & Stimulus Controller approach with w-messages (Aman Pandey)SnippetViewSet.on_register() (Sage Abdullah)pageurl template tag (Satvik Vashisht)window.initSlugAutoPopulate behavior to a Stimulus Controller w-sync (Loveth Omokaro)status classes to w-status to align with preferred CSS class naming conventions (Mansi Gundre)wagtail.test.utils to avoid cross-dependency issues (Matt Westcott)w-bulk, remove inline script usage (Hanoon)SnippetViewSet to extend ModelViewSet (Sage Abdullah)w-disimissible (Loveth Omokaro)w-autosize controller using autosize npm package v6 (Suyash Srivastava)w-action controller to support a click method (Suyash Srivastava)w-action controller usage (Aadi jindal, LB (Ben) Johnston)The following features deprecated in Wagtail 3.0 have been fully removed. See Wagtail 3.0 release notes for details on these changes, including how to remove usage of these features:
wagtail.core, wagtail.tests, wagtail.admin.edit_handlers and wagtail.contrib.forms.edit_handlers are removed.StreamFieldPanel, RichTextFieldPanel, ImageChooserPanel, DocumentChooserPanel and SnippetChooserPanel are removed.use_json_field=True (except migrations created before Wagtail 5.0).BASE_URL setting is no longer recognized.ModelAdmin.get_form_fields_exclude method is no longer passed a request argument.ModelAdmin.get_edit_handler method is no longer passed a request or instance argument.widget_overrides, required_fields, required_formsets, bind_to, render_as_object and render_as_field methods on Panel (previously EditHandler) are removed.The following features deprecated in Wagtail 4.0 have been fully removed. See Wagtail 4.0 release notes for details on these changes, including how to remove usage of these features:
wagtail.contrib.settings.models.BaseSetting class is removed.Page.get_latest_revision_as_page method is removed.page and page_id properties and as_page_object method on Revision are removed.createPageChooser, createSnippetChooser, createDocumentChooser and createImageChooser are removed.wagtail.contrib.modeladmin.menus.SubMenu class is removed.wagtail.contrib.modeladmin.helpers.AdminURLHelper are now required to accept a base_url_path keyword argument on the constructor.wagtail.admin.widgets.chooser.AdminChooser class is removed.wagtail.snippets.views.snippets.get_snippet_edit_handler function is removed.Django 4.0 reached end of life on 1st April 2023 and is no longer supported by Wagtail. Django 3.2 (LTS) is still supported until April 2024.
searchThe search method on pages, images and documents, and on the backend object returned by wagtail.search.backends.get_search_backend(), no longer performs partial word matching when the Elasticsearch backend is in use. Previously, a search query such as Page.objects.search("cat") would return results containing the word "caterpillar", while Page.objects.search("cat", partial_match=False) would only return results for the exact word "cat". The search method now always performs exact word matches, and the partial_match argument has no effect. This change makes the Elasticsearch backend consistent with the database-backed full-text search backends.
To revert to the previous partial word matching behavior, use the autocomplete method instead - for example, Page.objects.autocomplete("cat"). It may also be necessary to add an entry for the relevant fields on the model's search_fields definition, as the old SearchField("some_field", partial_match=True) format is no longer supported.
The partial_match argument on search and SearchField is now deprecated, and should be removed from your code; it will be dropped entirely in Wagtail 6.
When introduced in Wagtail 4.1, the ReferenceIndex model recorded references across all of a project's models by default. The default set of models being indexed has now been changed to only those used within the Wagtail admin, specifically:
This change will remove the impact of the indexing on non-Wagtail apps and models.
If you have models that still require reference indexing, and which are not registered as snippets or with ModelAdmin, you will need to explicitly register them within your app's AppConfig.ready() method. See Reference index for further details.
The use of wagtail_reference_index_ignore to prevent indexing of models is unchanged, but in many cases it may no longer be necessary.
It is recommended that the rebuild_references_index management command is run after the upgrade to remove any unnecessary records.
Page.get_static_site_paths method removedThe undocumented Page.get_static_site_paths method (which returns a generator of URL paths for use by static site generator packages) has been removed. Packages relying on this functionality should provide their own fallback implementation.
(wagtailsearch_query_migration)=
wagtailsearch.Query has moved to wagtail.contrib.search_promotionsThe wagtailsearch.Query model has been moved from the search application to the contrib application wagtail.contrib.search_promotions.
All imports will need to be updated and migrations will need to be run via a management command, some imports will still work with a warning until a future version.
To continue using the Query model, you must also add the wagtail.contrib.search_promotions application to your project's INSTALLED_APPS setting.
If you have daily hits records in the wagtailsearch.Query you can run the management command to move these records to the new location.
./manage.py copy_daily_hits_from_wagtailsearch
The search_garbage_collect command used to remove old stored search queries and daily hits has been moved to searchpromotions_garbage_collect.
| Import | Old import | New import |
|---|---|---|
Query Model |
from wagtail.search.models import Query |
from wagtail.contrib.search_promotions.models import Query |
QueryForm |
from wagtail.search.forms import QueryForm |
from wagtail.contrib.search_promotions.forms import QueryForm |
ModelAdmin templatesIf there are custom styles in place for the ModelAdmin's header content or more complex template overrides in use, there are a few changes for the following classes to be aware of.
| Content | Old classes | New classes |
|---|---|---|
Heading & search (contains h1) |
.left.header-left |
.left |
Action buttons (header_extra) |
.right.header-right |
.right |
The slug field JavaScript behavior was previously attached to any field with an ID of id_slug, this has now changed to be any field with the appropriate Stimulus data attributes.
If using a custom edit handler or set of panels for page models, the correct widget will now need to be used for these data attributes to be included. This widget will use the WAGTAIL_ALLOW_UNICODE_SLUGS Django setting.
from wagtail.admin.widgets.slug import SlugInput
# ... other imports
class MyPage(Page):
promote_panels = [
FieldPanel("slug", widget=SlugInput),
# ... other panels
]
Additionally, the slug behavior can be attached to any field easily by including the following attributes in HTML or via Django's widget attrs.
<input
type="text"
name="slug"
data-controller="w-slug"
data-action="blur->w-slug#slugify"
/>
To allow unicode values, add the data attribute value;
<input
type="text"
name="slug"
data-controller="w-slug"
data-action="blur->w-slug#slugify"
data-w-slug-allow-unicode-value="true"
/>
The mechanism for synchronizing the slug field with the page title has changed, and is no longer hard-coded to activate on fields named 'title'. Notably, this change affects page panel definitions that use FieldPanel("title") directly (rather than the convention of extending Page.content_panels), as well as non-page models such as snippets.
To assist in upgrading these definitions, Wagtail 5.0.2 provides a new class to be used in place of FieldPanel("title"). For example:
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
# ...
content_panels = [
MultiFieldPanel([
FieldPanel("title"),
FieldPanel("subtitle"),
]),
]
should become:
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, TitleFieldPanel
# ...
content_panels = [
MultiFieldPanel([
TitleFieldPanel("title"),
FieldPanel("subtitle"),
]),
]
If you have made deeper customizations to this behavior, or are unable to upgrade to Wagtail 5.0.2 or above, please read on as you may need to make some changes to adopt the new approach.
The title field will sync its value with the slug field on Pages if the Page is not published and the slug has not been manually changed. This JavaScript behavior previously attached to any field with an ID of id_title; this has now changed to be any field with the appropriate Stimulus data attributes.
There is a new Stimulus controller w-sync which allows any field to change one or more other fields when its value changes, the other field in this case will be the slug field (w-slug) with the id id_slug.
If you need to hook into this behavior, the new approach will now correctly dispatch change events on the slug field. Alternatively, you can modify the data attributes on the fields to adjust this behavior.
To adjust the target field (the one to be updated), you cam modify "data-w-sync-target-value", the default being "body:not(.page-is-live) [data-edit-form] #id_slug" (find the field with id id_slug when the page is not live).
To adjust what triggers the initial check (to see if the fields should be in sync), or the trigger the sync, you can use the Stimulus data-action attributes.
<input
id="id_title"
type="text"
name="title"
data-controller="w-sync"
data-action="focus->w-sync#check blur->w-sync#apply change->w-sync#apply"
data-w-sync-target-value="body:not(.page-is-live) #some_other_slug"
/>
Above we have adjusted these attributes to add a 'change' event listener to trigger the sync and also adjusted to look for a field with some_other_slug instead.
If you are using the wagtail.admin.widgets.AdminAutoHeightTextInput only, this change will have no impact when upgrading. However, if you are relying on the global autosize function at window.autosize on the client, this will no longer work.
It is recommended that the AdminAutoHeightTextInput widget be used instead. You can also adopt the data-controller attribute and this will now function as before. Alternatively, you can simply add the required Stimulus data controller attribute as shown below.
Old syntax
<textarea id="story" name="story">It was a dark and stormy night...</textarea>
<script>window.autosize($('story'));</script>
New syntax
<textarea name="story" data-controller="w-autosize">It was a dark and stormy night...</textarea>
There are no additional data attributes supported at this time.
button-longrunning) now relies on data attributesThe button-longrunning class usage has been updated to use the newly adopted Stimulus approach, the previous data attributes will be deprecated in a future release.
If using the old approach, ensure any HTML templates are updated to the new approach before the next major release.
Old syntax
<button type="submit" class="button action-save button-longrunning" data-clicked-text="{% trans 'Creating…' %}">
{% icon name="spinner" %}
<em>{% trans 'Create' %}</em>
</button>
New syntax
Minimum required attributes are data-controller and a data-action.
<button type="submit" class="button action-save button-longrunning" data-controller="w-progress" data-action="w-progress#activate" data-w-progress-active-value="{% trans 'Creating…' %}">
{% icon name="spinner" %}
<em data-w-progress-target="label">{% trans 'Create' %}</em>
</button>
Stimulus targets and actions can be leveraged to revise the behavior via data attributes.
<button ... data-w-progress-duration-value="500" ...> - custom duration can be declared on the element<button ... class="custom-button" data-w-progress-active-class="custom-button--busy" ...> - custom 'active' class to replace the default button-longrunning-active (must be a single string without spaces)<button ... ><strong data-w-progress-target="label">{% trans 'Create' %}</strong></button> - any element can be the button label (not just em)<button ... data-action="w-progress#activate focus->w-progress#activate" ...> - any event can be used to trigger the in progress behavior<button ... data-action="w-progress#activate:once" ...> - only trigger the progress behavior once<button ... data-action="readystatechange@document->w-progress#activate:once" data-w-progress-duration-value="5000" disabled ...> - disabled on load (once JS starts) and becomes enabled after 5s durationwindow.addMessages replaced with event dispatchingThe undocumented window.addMessage function is no longer available and will throw an error if called, if similar functionality is required use DOM Event dispatching instead as follows.
// old
window.addMessage('success', 'Content has updated');
// new
document.dispatchEvent(
new CustomEvent('w-messages:add', {
detail: { text: 'Content has updated', type: 'success' },
}),
);
// new (clearing existing messages before adding a new one)
document.dispatchEvent(
new CustomEvent('w-messages:add', {
detail: {
clear: true,
text: 'All content has updated',
type: 'success',
},
}),
);
// message types 'success', 'error', 'warning' are supported
Note that this event name may change in the future and this functionality is still not officially supported.
ValidationError classesThe client-side handling of StreamField validation errors has been updated. The JavaScript classes StreamBlockValidationError, ListBlockValidationError, StructBlockValidationError and TypedTableBlockValidationError have been removed, and the corresponding Python classes can no longer be serialized using Telepath. Instead, the setError methods on client-side block objects now accept a plain JSON representation of the error, obtained from the as_json_data method on the Python class. Custom JavaScript code that works with these objects must be updated accordingly.
Additionally, the Python StreamBlockValidationError, ListBlockValidationError, StructBlockValidationError and TypedTableBlockValidationError classes no longer provide a params dict with block_errors and non_block_errors items; these are now available as the attributes block_errors and non_block_errors on the exception itself (or cell_errors and non_block_errors in the case of TypedTableBlockValidationError).
delete-multiple view removedThe ability to remove multiple snippet instances from the DeleteView and the undocumented wagtailsnippets_{app_label}_{model_name}:delete-multiple URL pattern have been removed. The view's functionality has been replaced by the delete action of the bulk actions feature introduced in Wagtail 4.0.
The delete bulk action view now also calls the {before,after}_delete_snippet hooks, in addition to the {before,after}_bulk_action hooks.
If you have customized the IndexView and/or DeleteView views in a SnippetViewSet subclass, make sure that the delete_multiple_url_name attribute is renamed to delete_url_name.
The template name for the index view of a snippet model has changed from wagtailsnippets/snippets/type_index.html and wagtailsnippets/snippets/results.html to wagtailsnippets/snippets/index.html and wagtailsnippets/snippets/index_results.html. In addition, the model index view that lists the snippet types now looks for the template wagtailsnippets/snippets/model_index.html before resorting to the generic index template. If you have customized these templates, make sure to update them accordingly.
status classes are now w-statusPlease update any custom styling or usage within the admin when working with status tags to the following new classes.
| Old | New |
|---|---|
status-tag |
w-status |
primary |
w-status--primary |
disabled |
w-status--disabled |
status-tag--label |
w-status--label |
Note that a new template tag has been built for usage within the admin that may make it easier to generate status tags.
{% load wagtailadmin_tags %}
{% status "live" url="/test-url/" title=trans_title hidden_label=trans_hidden_label classname="w-status--primary" attrs='target="_blank" rel="noreferrer"' %}
{% status status_label classname="w-status--primary" %}
The Wagtail icon font has been deprecated and will be removed in a future release, as it is now unused in Wagtail itself. There are no changes to make for any icons usage via dedicated APIs such as icon class properties. Any direct icon font usage needs to be converted to SVG icons instead, as documented in our icons overview.
To check whether your project uses the icon font, check for occurrences of:
wagtail.woff font file.font-family: wagtail in CSS.icon-<name> CSS classes outside of SVG elements.The following icons are unused in Wagtail itself and will be removed in a future release. If you are using any of these icons, please replace them with an alternative (see our full list of icons), or re-add the icon to your own project.
| Icon name | Alternative |
|---|---|
angle-double-left |
arrow-left |
angle-double-right |
arrow-right |
arrow-down-big |
arrow-down |
arrow-up-big |
arrow-up |
arrows-up-down |
order |
chain-broken |
link |
chevron-down |
arrow-down (identical) |
dots-vertical |
dots-horizontal |
download-alt |
download (identical) |
duplicate |
copy (identical) |
ellipsis-v |
dots-horizontal |
horizontalrule |
minus |
repeat |
rotate |
reset |
rotate |
tick |
check (identical) |
undo |
rotate |
uni52 |
folder-inverse (identical) |
wagtail-inverse |
wagtail-icon |
get_admin_url_namespace() and get_admin_base_path() moved to SnippetViewSetThe undocumented get_admin_url_namespace() and get_admin_base_path() methods that were set on snippet models at runtime have been moved to the {class}~wagtail.snippets.views.snippets.SnippetViewSet class. If you use these methods, you could access them via {meth}SnippetModel.snippet_viewset.get_admin_url_namespace() <wagtail.snippets.views.snippets.SnippetViewSet.get_admin_url_namespace> and {meth}SnippetModel.snippet_viewset.get_admin_base_path() <wagtail.snippets.views.snippets.SnippetViewSet.get_admin_base_path>, respectively.
get_usage() and usage_url() methods removedThe undocumented get_usage() and usage_url() methods that were set on snippet models at runtime have been removed. Calls to the get_usage() method can be replaced with wagtail.models.ReferenceIndex.get_grouped_references_to(object). The usage_url() method does not have a direct replacement, but the URL name can be retrieved via {meth}SnippetModel.snippet_viewset.get_url_name("usage") <wagtail.admin.viewsets.base.ViewSet.get_url_name>, which can be used to construct the URL with {func}~django.urls.reverse.
Maintenance: Removed features deprecated in Wagtail 3.0 and 4.0 (Matt Westcott)
WAGTAILIMAGES_EXTENSIONS setting to restrict image uploads to specific file types (Aman Pandey, Ananjan-R)Access level to be easier to understand (Vallabh Tiwari).button-longrunning behaviour to a Stimulus controller with support for custom label element & duration (Loveth Omokaro)change event (George Sakkis)search_fields = [] (Daniel Kirkham)wagtail.search.utils.parse_query_string to allow inner single quotes for key/value parsing (Aman Pandey)Locale for more convenient usage within templates (Andy Babic)SnippetViewSet.icon (Daniel Kirkham, Sage Abdullah)MenuItem.name for Snippets, Reports, and Settings menu items (Sage Abdullah)list_filter attribute (Sage Abdullah)IndexView (Sage Abdullah)search_fields and search backend via SnippetViewSet (Sage Abdullah)panels / edit_handler to be specified via SnippetViewSet (Sage Abdullah)label_format on StructBlock gracefully handles missing variables (Aadi jindal)Site.get_site_root_paths works on cache backends that do not preserve Python objects (Jaap Roes)StructValue copies (Tidiane Dia)GroupApprovalTask if it's locked by someone outside of the group (Sage Abdullah)WorkflowLock is currently applied (Sage Abdullah)wagtail.schedule.cancel (Stefan Hammer)require_admin_access() (Stefan Hammer)radio input fields (Mehul Aggarwal)TemplateResponses for users with a custom timezone (Stefan Hammer, Sage Abdullah)download_url when WAGTAILDOCS_SERVE_METHOD is direct (Swojak-A)ClusterableModel requirements for using relations with RevisionMixin-enabled models (Sage Abdullah)strictPropertyInitialization in tsconfig (Thibaud Colas)Page.get_static_site_paths method (Yosr Karoui)CollapseAll and MinimapItem components (Albina Starykova)AutoFieldController to the less confusing SubmitController (Loveth Omokaro)script tags with template tag for image/document bulk uploads (Rishabh Kumar Bahukhandi)SlugInput widget (Loveth Omokaro)status HTML usage to shared template tag (Aman Pandey, LB (Ben) Johnston, Himanshu Garg)ModelAdmin and Snippets type index header (Aman Pandey)wagtailsearch.Query to wagtail.contrib.search_promotions (Karl Hobley)initErrorDetection (tabs error counts) to a Stimulus Controller w-count (Aman Pandey)window.addMessage behaviour to a global event listener & Stimulus Controller approach with w-messages (Aman Pandey)SnippetViewSet.on_register() (Sage Abdullah)pageurl template tag (Satvik Vashisht)window.initSlugAutoPopulate behaviour to a Stimulus Controller w-sync (Loveth Omokaro)status classes to w-status to align with preferred CSS class naming conventions (Mansi Gundre)wagtail.test.utils to avoid cross-dependency issues (Matt Westcott)w-bulk, remove inline script usage (Hanoon)SnippetViewSet to extend ModelViewSet (Sage Abdullah)w-disimissible (Loveth Omokaro)w-autosize controller using autosize npm package v6 (Suyash Srivastava)w-action controller to support a click method (Suyash Srivastava)w-action controller usage (Aadi jindal, LB (Ben) Johnston)Fix: Rectify previous fix for TableBlock becoming uneditable after save (Sage Abdullah)
log_action parameter on RevisionMixin.save_revision (Christer Jensen)log_action parameter on RevisionMixin.save_revision (Christer Jensen)May 25, 2023
---
local:
depth: 1
---
log_action parameter on RevisionMixin.save_revision (Christer Jensen)Fix: Prevent TableBlock from becoming uneditable after save (Sage Abdullah)
May 2, 2023
---
local:
depth: 1
---
Fix: CVE-2023-28836 - Stored XSS attack via ModelAdmin views (Thibaud Colas)
TemplateResponses for users with a custom timezone (Stefan Hammer, Sage Abdullah)MultipleChooserPanel in panel reference docsApril 3, 2023
---
local:
depth: 1
---
This release addresses a stored cross-site scripting (XSS) vulnerability on ModelAdmin views within the Wagtail admin interface. A user with a limited-permission editor account for the Wagtail admin could potentially craft pages and documents that, when viewed by a user with higher privileges, could perform actions with that user's credentials. The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin, and only affects sites with ModelAdmin enabled.
Many thanks to Thibaud Colas for reporting this issue. For further details, please see the CVE-2023-28836 security advisory.
This release addresses a memory exhaustion bug in Wagtail's handling of uploaded images and documents. For both images and documents, files are loaded into memory during upload for additional processing. A user with access to upload images or documents through the Wagtail admin interface could upload a file so large that it results in a crash or denial of service.
The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin. It can only be exploited by admin users with permission to upload images or documents.
Many thanks to Jake Howard for reporting this issue. For further details, please see the CVE-2023-28837 security advisory.
TemplateResponses for users with a custom timezone (Stefan Hammer, Sage Abdullah)MultipleChooserPanel in panel reference docsFix: Support creating StructValue copies (Tidiane Dia)
StructValue copies (Tidiane Dia)GroupApprovalTask if it's locked by someone outside of the group (Sage Abdullah)wagtail.schedule.cancel (Stefan Hammer)require_admin_access() (Stefan Hammer)ClusterableModel requirements for using relations with RevisionMixin-enabled models (Sage Abdullah)March 13, 2023
---
local:
depth: 1
---
StructValue copies (Tidiane Dia)GroupApprovalTask if it's locked by someone outside of the group (Sage Abdullah)wagtail.schedule.cancel (Stefan Hammer)require_admin_access() (Stefan Hammer)ClusterableModel requirements for using relations with RevisionMixin-enabled models (Sage Abdullah)Maintenance: Add deprecation warnings for wagtail.core and other imports deprecated in Wagtail 3.0 (Matt Westcott)
LockableMixin (Sage Abdullah)WorkflowMixin (Sage Abdullah){% fullpageurl %} tag for getting the absolute URL of a page (Jake Howard)MultipleChooserPanel, a variant of InlinePanel with improved editor experience when inserting multiple linked objects (Matt Westcott)WagtailPageTestCase.assertCanCreate now supports the kwarg publish=True to determine whether to publish the page (Harry Percival, Akua Dokua Asiedu, Matt Westcott)rebuild_references_index command can run without console output if called with --verbosity 0 (Omerzahid Ali, Aman Pandey)button bicolor button--icon button-secondary including the button-small variant (Seremba Patrick)purge_embeds management command to delete all the cached embed objects in the database (Aman Pandey)form_fields as an APIField on FormPage (Sævar Öfjörð Magnússon, Suyash Singh, LB (Ben) Johnston)DraftStateMixin now automatically define a "Publish" permission type (Sage Abdullah)azure-mgmt-cdn version >= 10 and azure-mgmt-frontdoor version >= 1 in the frontend cache invalidator (Sylvain Fankhauser)django-storages backend is configured to allow overwriting (Rishabh jain)construct_wagtail_userbar hook (Sage Abdullah)InlinePanel inner fields to avoid lost or incorrectly linked comments (Jacob Topp-Mugglestone)WAGTAILIMAGES_FEATURE_DETECTION_ENABLED to avoid errors for images that do not exist (Aman Pandey)cc, bcc and reply_to to the Django mail helper from wagtail.admin.mail.send_mail (Ben Gosney)DecimalBlock correctly handles None, when required=False, values (Natarajan Balaji)delete_url_name attribute in generic DeleteView (Alex Simpson)wagtail.search.utils.parse_query_string (Beniamin Bucur)workflow_state_approved.html template (Alex Tomkins)latest_revision pointer from being copied over when copying translatable snippets for translation (Sage Abdullah)fnm over nvm in development documentation (LB (Ben) Johnston)request and current_site to get_url on the performance documentation page (Jake Howard)register_user_listing_buttons hook (LB (Ben Johnston))page models usage guide (Damilola Oladele)register_image_operations and add an example of a custom Image filter (Coen van der Kamp)RichTextField (Matt Westcott)renderer_classes (Aman Pandey)testapp migrations (Matt Westcott)escapeHtml function (Jordan Rob)initButtonSelects from core.js to own TypesScript file and add unit tests (Loveth Omokaro)initSkipLink util to TypeScript and add JSDoc & unit tests (Juliet Adeboye)unlist to Tailwind utility class w-list-none (Loveth Omokaro)hasOwn in TypeScript (Loveth Omokaro)initTooltips to TypeScript add JSDoc and unit tests (Fatuma Abdullahi)initTagField from core.js to own TypeScript file and add unit tests (Chisom Okeoma)initDissmisibles (Yekasumah)classname for passing HTML class attributes (LB (Ben Johnston))InlinePanel JavaScript initialisation code and adopt a class approach (Matt Westcott)identity JavaScript util into shared utils folder (LB (Ben Johnston))URLSearchParams (Loveth Omokaro)tsconfig to better support modern TypeScript development and clean up some code quality issues via Eslint (Loveth Omokaro)wagtail.admin.panels into submodules, existing exports have been preserved (Matt Westcott)wagtail.core and other imports deprecated in Wagtail 3.0 (Matt Westcott)avatar component with a template tag include {% avatar ... %} throughout the admin interface (Aman Pandey)LockableMixin (Sage Abdullah)WorkflowMixin (Sage Abdullah){% fullpageurl %} tag for getting the absolute URL of a page (Jake Howard)MultipleChooserPanel, a variant of InlinePanel with improved editor experience when inserting multiple linked objects (Matt Westcott)WagtailPageTestCase.assertCanCreate now supports the kwarg publish=True to determine whether to publish the page (Harry Percival, Akua Dokua Asiedu, Matt Westcott)rebuild_references_index command can run without console output if called with --verbosity 0 (Omerzahid Ali, Aman Pandey)button bicolor button--icon button-secondary including the button-small variant (Seremba Patrick)purge_embeds management command to delete all the cached embed objects in the database (Aman Pandey)form_fields as an APIField on FormPage (Sævar Öfjörð Magnússon, Suyash Singh, LB (Ben) Johnston)DraftStateMixin now automatically define a "Publish" permission type (Sage Abdullah)azure-mgmt-cdn version >= 10 and azure-mgmt-frontdoor version >= 1 in the frontend cache invalidator (Sylvain Fankhauser)django-storages backend is configured to allow overwriting (Rishabh jain)construct_wagtail_userbar hook (Sage Abdullah)InlinePanel inner fields to avoid lost or incorrectly linked comments (Jacob Topp-Mugglestone)WAGTAILIMAGES_FEATURE_DETECTION_ENABLED to avoid errors for images that do not exist (Aman Pandey)cc, bcc and reply_to to the Django mail helper from wagtail.admin.mail.send_mail (Ben Gosney)DecimalBlock correctly handles None, when required=False, values (Natarajan Balaji)delete_url_name attribute in generic DeleteView (Alex Simpson)wagtail.search.utils.parse_query_string (Beniamin Bucur)workflow_state_approved.html template (Alex Tomkins)latest_revision pointer from being copied over when copying translatable snippets for translation (Sage Abdullah)fnm over nvm in development documentation (LB (Ben) Johnston)request and current_site to get_url on the performance documentation page (Jake Howard)register_user_listing_buttons hook (LB (Ben Johnston))page models usage guide (Damilola Oladele)register_image_operations and add an example of a custom Image filter (Coen van der Kamp)RichTextField (Matt Westcott)renderer_classes (Aman Pandey)SettingsPanel reference in the page editing TabbedInterface example as SettingsPanel no longer shows anything as of 4.1 (Kenny Wolf, Julian Bigler)permission kwarg support in Panels (LB (Ben) Johnston)testapp migrations (Matt Westcott)escapeHtml function (Jordan Rob)initButtonSelects from core.js to own TypeScript file and add unit tests (Loveth Omokaro)initSkipLink util to TypeScript and add JSDoc & unit tests (Juliet Adeboye)unlist to Tailwind utility class w-list-none (Loveth Omokaro)hasOwn in TypeScript (Loveth Omokaro)initTooltips to TypeScript and add JSDoc and unit tests (Fatuma Abdullahi)initTagField from core.js to own TypeScript file and add unit tests (Chisom Okeoma)initDismissibles (Yekasumah)classname for passing HTML class attributes (LB (Ben Johnston))InlinePanel JavaScript initialization code and adopt a class approach (Matt Westcott)identity JavaScript util into shared utils folder (LB (Ben Johnston))URLSearchParams (Loveth Omokaro)tsconfig to better support modern TypeScript development and clean up some code quality issues via Eslint (Loveth Omokaro)wagtail.admin.panels into submodules, existing exports have been preserved (Matt Westcott)wagtail.core and other imports deprecated in Wagtail 3.0 (Matt Westcott)avatar component with a template tag include {% avatar ... %} throughout the admin interface (Aman Pandey)icon-help and help-inverse code (Thibaud Colas)c-, o-, u-, t-, is- prefixes (Thibaud Colas)3.2, 4.0, 4.1
3.7, 3.8, 3.9, 3.10, 3.11
4.1 LTS
3.2, 4.0, 4.1
3.7, 3.8, 3.9, 3.10, 3.11
February 6, 2023
---
local:
depth: 1
---
Wagtail now provides a set of utilities for creating data migrations on StreamField data. For more information, see StreamField data migrations. This feature was developed by Sandil Ranasinghe, initially as the wagtail-streamfield-migration-toolkit add-on package, as part of the Google Summer of Code 2022 initiative, with support from Jacob Topp-Mugglestone, Joshua Munn and Karl Hobley.
Snippets can now be locked by users to prevent other users from editing, through the use of the LockableMixin. For more details, see .
This feature was developed by Sage Abdullah.
Snippets can now be assigned to workflows through the use of the WorkflowMixin, allowing new changes to be submitted for moderation before they are published. For more details, see .
This feature was developed by Sage Abdullah.
fullpageurl template tagWagtail now provides a fullpageurl template tag (for both Django templates and Jinja2) to output a page's full URL including the domain. For more details, see .
This feature was developed by Jake Howard.
Wagtail now uses the Stimulus framework for client-side interactivity (see RFC 78). Our Outreachy contributor Loveth Omokaro has refactored significant portions of the admin interface:
Those changes improve the maintainability of the code, and help us move towards compatibility with strict CSP (Content Security Policy) rules. Thank you to Loveth and project mentors LB (Ben) Johnston, Thibaud Colas, and Paarth Agarwal.
The CMS now includes an accessibility checker in the user bar, to assist users in building more accessible websites and follow ATAG 2.0 guidelines. The checker, which is based on the Axe testing engine, is designed for content authors to identify and fix accessibility issues on their own. It scans the loaded page for errors and displays the results, with three rules turned on in this release. It’s configurable with the construct_wagtail_userbar hook.
This new feature was implemented by Albina Starykova as part of an Outreachy internship, with support from mentors Thibaud Colas, Sage Abdullah, and Joshua Munn.
Following feedback from Wagtail users on rich text UI improvements in Wagtail 4.0, we have further refined the behavior of rich text fields to cater for different scenarios:
Thank you to all who provided feedback, participants to our usability testing sessions, and to Nick Lee and Thibaud Colas for the implementation.
A new panel type is available. This is a variant of InlinePanel which improves the editor experience when adding large numbers of linked items - rather than creating and populating each sub-form individually, a chooser modal is opened allowing multiple objects to be selected at once.
This feature was developed by Matt Westcott, and sponsored by YouGov.
WagtailPageTestCase.assertCanCreate now supports the kwarg publish=True to determine whether to publish the page (Harry Percival, Akua Dokua Asiedu, Matt Westcott)rebuild_references_index command can run without console output if called with --verbosity 0 (Omerzahid Ali, Aman Pandey)button bicolor button--icon button-secondary including the button-small variant (Seremba Patrick)purge_embeds management command to delete all the cached embed objects in the database (Aman Pandey)form_fields as an APIField on FormPage (Sævar Öfjörð Magnússon, Suyash Singh, LB (Ben) Johnston)DraftStateMixin now automatically define a "Publish" permission type (Sage Abdullah)azure-mgmt-cdn version >= 10 and azure-mgmt-frontdoor version >= 1 in the frontend cache invalidator (Sylvain Fankhauser)django-storages backend is configured to allow overwriting (Rishabh Jain)ChooserBlock.extract_references uses the model class, not the model string (Alex Tomkins)InlinePanel inner fields to avoid lost or incorrectly linked comments (Jacob Topp-Mugglestone)WAGTAILIMAGES_FEATURE_DETECTION_ENABLED to avoid errors for images that do not exist (Aman Pandey)cc, bcc and reply_to to the Django mail helper from wagtail.admin.mail.send_mail (Ben Gosney)DecimalBlock correctly handles None, when required=False, values (Natarajan Balaji)delete_url_name attribute in generic DeleteView (Alex Simpson)wagtail.search.utils.parse_query_string (Beniamin Bucur)latest_revision pointer from being copied over when copying translatable snippets for translation (Sage Abdullah)fnm over nvm in development documentation (LB (Ben) Johnston)request and current_site to get_url on the performance documentation page (Jake Howard)register_user_listing_buttons hook (LB (Ben Johnston))page models usage guide (Damilola Oladele)register_image_operations and add an example of a custom Image filter (Coen van der Kamp)RichTextField (Matt Westcott)renderer_classes (Aman Pandey)testapp migrations (Matt Westcott)escapeHtml function (Jordan Rob)initButtonSelects from core.js to own TypeScript file and add unit tests (Loveth Omokaro)initSkipLink util to TypeScript and add JSDoc & unit tests (Juliet Adeboye)unlist to Tailwind utility class w-list-none (Loveth Omokaro)hasOwn in TypeScript (Loveth Omokaro)initTooltips to TypeScript and add JSDoc and unit tests (Fatuma Abdullahi)initTagField from core.js to own TypeScript file and add unit tests (Chisom Okeoma)initDismissibles (Yekasumah)classname for passing HTML class attributes (LB (Ben Johnston))InlinePanel JavaScript initialization code and adopt a class approach (Matt Westcott)identity JavaScript util into shared utils folder (LB (Ben Johnston))URLSearchParams (Loveth Omokaro)tsconfig to better support modern TypeScript development and clean up some code quality issues via Eslint (Loveth Omokaro)wagtail.admin.panels into submodules, existing exports have been preserved (Matt Westcott)wagtail.core and other imports deprecated in Wagtail 3.0 (Matt Westcott)avatar component with a template tag include {% avatar ... %} throughout the admin interface (Aman Pandey)WagtailImageField)The AbstractImage and AbstractRendition models use a Wagtail-specific WagtailImageField which extends Django's ImageField
to use Willow for image file handling. This will generate a new migration if you
are using a custom image model.
InlinePanel not supportedWhen the commenting system was introduced, support for InlinePanel fields was incorrectly added. This has led to issues
where comments can be lost on save, or in most cases will be added to the incorrect item within the InlinePanel. The ability
to add comments here has now been removed and as such any existing comments that were added will no longer show.
See https://github.com/wagtail/wagtail/issues/9685 for tracking of adding this back officially in the future.
classname convention for some template tags & includesSome undocumented Wagtail admin template tags and includes have been refactored to adopt a more consistent naming of classname.
If these are used within packages or customizations they will need to be updated to the new variable naming convention.
| Name | New (classname) |
Old (various) |
|---|---|---|
icon (see note) |
{% icon name='spinner' classname='...' %} |
{% icon name='spinner class_name='...' %} |
dialog_toggle |
{% dialog_toggle classname='...' %} |
{% dialog_toggle class_name='...' %} |
paginate |
{% paginate pages classname="..." %} |
{% paginate pages classnames="..." %} |
tab_nav_link |
{% include 'wagtailadmin/shared/tabs/tab_nav_link.html' with classname="..." %} |
{% include 'wagtailadmin/shared/tabs/tab_nav_link.html' with classes="..." %} |
side_panel_button |
{% include 'wagtailadmin/shared/side_panels/includes/side_panel_button.html' with classname="..." %} |
{% include 'wagtailadmin/shared/side_panels/includes/side_panel_button.html' with classes="..." %} |
Note that the icon template tag will still support class_name with a deprecation warning. Support will be dropped in a future release.
InlinePanel JavaScript function is now a classThe (internal, undocumented) InlinePanel JavaScript function, used to initialize client-side behavior for inline panels, has been converted to a class. Any user code that calls this function should now replace InlinePanel(...) calls with new InlinePanel(...). Additionally, child form controls are now initialized automatically, and so it is no longer necessary to call initChildControls, updateChildCount, updateMoveButtonDisabledStates or updateAddButtonState.
Python code that uses the InlinePanel panel type is not affected by this change.
WAGTAILADMIN_GLOBAL_PAGE_EDIT_LOCK setting is now WAGTAILADMIN_GLOBAL_EDIT_LOCKThe WAGTAILADMIN_GLOBAL_PAGE_EDIT_LOCK setting has been renamed to WAGTAILADMIN_GLOBAL_EDIT_LOCK.
The wagtailuserbar template tag now initializes the userbar as a Web Component, with a wagtail-userbar custom element using shadow DOM to apply styles without any collisions with the host page.
For any site customizing the position of the userbar, target the styles to wagtail-userbar::part(userbar) instead of .wagtail-userbar. For example:
wagtail-userbar::part(userbar) {
bottom: 30px;
}
Like other userbar items, the new accessibility checker is configurable with the construct_wagtail_userbar hook. For example, to remove the new item, use:
from wagtail.admin.userbar import AccessibilityItem
@hooks.register("construct_wagtail_userbar")
def remove_userbar_accessibility_checks(request, items):
items[:] = [item for item in items if not isinstance(item, AccessibilityItem)]
azure-mgmt-cdn and azure-mgmt-frontdoor packages will be droppedIf you are using the front-end cache invalidator module (wagtail.contrib.frontend_cache) with Azure CDN or Azure Front Door, the following packages need to be updated:
azure-mgmt-cdn to version 10 or aboveazure-mgmt-frontdoor to version 1 or aboveSupport for older versions will be dropped in a future release.
Workflow and Task methodsTo accommodate workflows support for snippets, the page parameter in {meth}Workflow.start() <wagtail.models.Workflow.start> has been renamed to obj.
In addition, some methods on the base {class}~wagtail.models.Task model have been changed. If you have {doc}custom Task types </extending/custom_tasks>, make sure to update the methods to reflect the following changes:
page_locked_for_user() is now {meth}~wagtail.models.Task.locked_for_user. Using page_locked_for_user() is deprecated and will be removed in a future release.page parameter in user_can_access_editor(), locked_for_user(), user_can_lock(), user_can_unlock(), get_actions(), has been renamed to obj.WorkflowState and TaskState modelsTo accommodate workflows support for snippets, the WorkflowState.page foreign key has been replaced with a GenericForeignKey as WorkflowState.content_object. The generic foreign key is defined using a combination of the new WorkflowState.base_content_type and WorkflowState.object_id fields.
The TaskState.page_revision foreign key has been renamed to TaskState.revision.
wagtail.admin.forms.search.SearchForm validation logicThe wagtail.admin.forms.search.SearchForm class (which is internal and undocumented, but may be in use by applications that extend the Wagtail admin) no longer treats an empty search field as invalid. Any code that checks form.is_valid to determine whether or not to apply a search() filter to a queryset should now explicitly check that form.cleaned_data["q"] is non-empty.
Maintenance: Add deprecation warnings for wagtail.core and other imports deprecated in Wagtail 3.0 (Matt Westcott)
LockableMixin (Sage Abdullah)WorkflowMixin (Sage Abdullah){% fullpageurl %} tag for getting the absolute URL of a page (Jake Howard)MultipleChooserPanel, a variant of InlinePanel with improved editor experience when inserting multiple linked objects (Matt Westcott)WagtailPageTestCase.assertCanCreate now supports the kwarg publish=True to check publish redirection (Harry Percival, Akua Dokua Asiedu)rebuild_references_index command can run without console output if called with --verbosity 0 (Omerzahid Ali, Aman Pandey)button bicolor button--icon button-secondary including the button-small variant (Seremba Patrick)purge_embeds management command to delete all the cached embed objects in the database (Aman Pandey)form_fields as an APIField on FormPage (Sævar Öfjörð Magnússon, Suyash Singh, LB (Ben) Johnston)DraftStateMixin now automatically define a "Publish" permission type (Sage Abdullah)azure-mgmt-cdn version >= 10 and azure-mgmt-frontdoor version >= 1 in the frontend cache invalidator (Sylvain Fankhauser)django-storages backend is configured to allow overwriting (Rishabh jain)construct_wagtail_userbar hook (Sage Abdullah)InlinePanel inner fields to avoid lost or incorrectly linked comments (Jacob Topp-Mugglestone)WAGTAILIMAGES_FEATURE_DETECTION_ENABLED to avoid errors for images that do not exist (Aman Pandey)cc, bcc and reply_to to the Django mail helper from wagtail.admin.mail.send_mail (Ben Gosney)DecimalBlock correctly handles None, when required=False, values (Natarajan Balaji)delete_url_name attribute in generic DeleteView (Alex Simpson)wagtail.search.utils.parse_query_string (Beniamin Bucur)fnm over nvm in development documentation (LB (Ben) Johnston)request and current_site to get_url on the performance documentation page (Jake Howard)register_user_listing_buttons hook (LB (Ben Johnston))page models usage guide (Damilola Oladele)register_image_operations and add an example of a custom Image filter (Coen van der Kamp)RichTextField (Matt Westcott)renderer_classes (Aman Pandey)testapp migrations (Matt Westcott)escapeHtml function (Jordan Rob)initButtonSelects from core.js to own TypesScript file and add unit tests (Loveth Omokaro)initSkipLink util to TypeScript and add JSDoc & unit tests (Juliet Adeboye)unlist to Tailwind utility class w-list-none (Loveth Omokaro)hasOwn in TypeScript (Loveth Omokaro)initTooltips to TypeScript add JSDoc and unit tests (Fatuma Abdullahi)initTagField from core.js to own TypeScript file and add unit tests (Chisom Okeoma)initDissmisibles (Yekasumah)classname for passing HTML class attributes (LB (Ben Johnston))InlinePanel JavaScript initialisation code and adopt a class approach (Matt Westcott)identity JavaScript util into shared utils folder (LB (Ben Johnston))URLSearchParams (Loveth Omokaro)tsconfig to better support modern TypeScript development and clean up some code quality issues via Eslint (Loveth Omokaro)wagtail.admin.panels into submodules, existing exports have been preserved (Matt Westcott)wagtail.core and other imports deprecated in Wagtail 3.0 (Matt Westcott)avatar component with a template tag include {% avatar ... %} throughout the admin interface (Aman Pandey)Fix: CVE-2023-45809: Disclosure of user names via admin bulk action views (Matt Westcott)
October 19, 2023
---
local:
depth: 1
---
This release addresses an information disclosure vulnerability in the Wagtail admin interface. A user with a limited-permission editor account for the Wagtail admin can make a direct URL request to the admin view that handles bulk actions on user accounts. While authentication rules prevent the user from making any changes, the error message discloses the display names of user accounts, and by modifying URL parameters, the user can retrieve the display name for any user. The vulnerability is not exploitable by an ordinary site visitor without access to the Wagtail admin.
Many thanks to quyenheu for reporting this issue. For further details, please see the CVE-2023-45809 security advisory.
Maintenance: Additionally update Pillow dependency to allow use of versions with security fixes (Dan Braghis)
September 28, 2023
---
local:
depth: 1
---
Maintenance: Relax Willow dependency to allow use of current Pillow versions with security fixes (Dan Braghis)
September 27, 2023
---
local:
depth: 1
---
Fix: Rectify previous fix for TableBlock becoming uneditable after save (Sage Abdullah)
log_action parameter on RevisionMixin.save_revision (Christer Jensen)May 25, 2023
---
local:
depth: 1
---
log_action parameter on RevisionMixin.save_revision (Christer Jensen)Fix: Prevent TableBlock from becoming uneditable after save (Sage Abdullah)
Fix: CVE-2023-28836 - Stored XSS attack via ModelAdmin views (Thibaud Colas)
TemplateResponses for users with a custom timezone (Stefan Hammer, Sage Abdullah)Fix: Add right-to-left (RTL) support for the following form components: Switch, Minimap, live preview (Thibaud Colas)
StructValue copies (Tidiane Dia)wagtail.schedule.cancel (Stefan Hammer)require_admin_access() (Stefan Hammer)ClusterableModel requirements for using relations with RevisionMixin-enabled models (Sage Abdullah)Fix: Make "Cancel scheduled publish" button correctly redirect back to the edit view (Sage Abdullah)
PreviewableMixin applied (Sage Abdullah)latest_revision pointer from being copied over when copying translatable snippets for translation (Sage Abdullah)Fix: Fix issue where lock/unlock buttons would not work on the Dashboard (home) page or the page index listing via the status sidebar (Stefan Hammer)
verbose_name property from breaking usage report views (Matt Westcott)CSRF_HEADER_NAME setting (Sage Abdullah)New scheduled publishing UI, available from the Status side panel (Sage Abdullah)
SnippetViewSet (Sage Abdullah)DraftStateMixin (Sage Abdullah)PageQuerySet.private method as an alias of not_public (Mehrdad Moradizadeh)unbutton, button-neutral, button-strokeonhover, hover-no, yes) and refactor button styles to be more maintainable (Paarth Agarwal, LB (Ben Johnston))AbstractFormField to FormMixin and AbstractEmailForm to EmailFormMixin to allow use with subclasses of Page (Mehrdad Moradizadeh, Kurt Wall)docs.wagtail.org/.well-known/security.txt so that the security policy is available as per the specification on https://securitytxt.org/ (Jake Howard)classnames Wagtail admin template tag (Mehrdad Moradizadeh)admonition should not be used and titles for note are not supported, including clean up of some existing incorrect usage (LB (Ben Johnston)).button-secondary buttons across the admin interface (Paarth Agarwal)button not link for behaviour (LB (Ben) Johnston)search type input in documentation search (LB (Ben) Johnston)help_text when set on FieldPanel, MultiFieldPanel, FieldRowPanel, and other panel APIs where it previously worked without official support (Matt Westcott)openpyxl, removing usage of XlsxWriter, tablib, xlrd and xlwt (Jaap Roes)wagtail.admin.views.generic.IndexView for the Users index listing and search results (Mehrdad Moradizadeh)wagtail.admin.views.generic.CreateView for the User creation view (Mehrdad Moradizadeh)wagtail.admin.views.generic.DeleteView for the User delete view (Mehrdad Moradizadeh)wagtail.admin.views.generic.EditView for the User edit view (Mehrdad Moradizadeh)button-secondary bicolor variants to the pattern library and styleguide (Adinapunyo Banerjee)id primary keys into Wagtail's generic views, including for Snippets and custom User models (Mehrdad Moradizadeh)<section> element so screen reader users can bypass them more easily (Thibaud Colas)update_index command can run without console output if called with --verbosity 0 (Ben Sturmfels, Oliver Parker)image_url template tag, when using the serve view to redirect rather than serve directly, will now use temporary redirects with a cache header instead of permanent redirects (Jake Howard)WagtailPageTestCase - assertPageIsRoutable, assertPageIsRenderable, assertPageIsEditable, assertPageIsPreviewable (Andy Babic)permission to PanelGroup, used by TabbedInterface, ObjectList, FieldRowPanel and MultiFieldPanel (Oliver Parker)PageQuerySet.not_public from returning all pages when no page restrictions exist (Mehrdad Moradizadeh)formfield_callback handling on ModelForm.Meta for future Django 4.2 release (Matt Westcott)ModelAdmin correctly supports filters in combination with subsequent searches without clearing the applied filters (Stefan Hammer)capitalize() calls to avoid issues with other languages or incorrectly presented model names for reporting and parts of site settings (Stefan Hammer)help_text for InlinePanel (Matt Westcott)for_user argument is passed to the form class when previewing pages (Matt Westcott)timesince_simple tag is consistently added in the template based on usage in context (Stefan Hammer)timesince_last_update and ensure the translated labels can be easier to work with in Transifex (Stefan Hammer)clean_name values in the Form Builder validation and increase performance of checks (Dan Bentley)wagtailsearch_editorspick table that prevents flushing the database (Matt Westcott)aria-labels (Matt Westcott)New scheduled publishing UI, available from the Status side panel (Sage Abdullah)
SnippetViewSet (Sage Abdullah)DraftStateMixin (Sage Abdullah)PageQuerySet.private method as an alias of not_public (Mehrdad Moradizadeh)unbutton, button-neutral, button-strokeonhover, hover-no, yes) and refactor button styles to be more maintainable (Paarth Agarwal, LB (Ben Johnston))AbstractFormField to FormMixin and AbstractEmailForm to EmailFormMixin to allow use with subclasses of Page (Mehrdad Moradizadeh, Kurt Wall)docs.wagtail.org/.well-known/security.txt so that the security policy is available as per the specification on https://securitytxt.org/ (Jake Howard)classnames Wagtail admin template tag (Mehrdad Moradizadeh)admonition should not be used and titles for note are not supported, including clean up of some existing incorrect usage (LB (Ben Johnston)).button-secondary buttons across the admin interface (Paarth Agarwal)button not link for behaviour (LB (Ben) Johnston)search type input in documentation search (LB (Ben) Johnston)help_text when set on FieldPanel, MultiFieldPanel, FieldRowPanel, and other panel APIs where it previously worked without official support (Matt Westcott)openpyxl, removing usage of XlsxWriter, tablib, xlrd and xlwt (Jaap Roes)wagtail.admin.views.generic.IndexView for the Users index listing and search results (Mehrdad Moradizadeh)wagtail.admin.views.generic.CreateView for the User creation view (Mehrdad Moradizadeh)wagtail.admin.views.generic.DeleteView for the User delete view (Mehrdad Moradizadeh)wagtail.admin.views.generic.EditView for the User edit view (Mehrdad Moradizadeh)button-secondary bicolor variants to the pattern library and styleguide (Adinapunyo Banerjee)id primary keys into Wagtail's generic views, including for Snippets and custom User models (Mehrdad Moradizadeh)<section> element so screen reader users can bypass them more easily (Thibaud Colas)update_index command can run without console output if called with --verbosity 0 (Ben Sturmfels, Oliver Parker)image_url template tag, when using the serve view to redirect rather than serve directly, will now use temporary redirects with a cache header instead of permanent redirects (Jake Howard)WagtailPageTestCase - assertPageIsRoutable, assertPageIsRenderable, assertPageIsEditable, assertPageIsPreviewable (Andy Babic)permission to PanelGroup, used by TabbedInterface, ObjectList, FieldRowPanel and MultiFieldPanel (Oliver Parker)PageQuerySet.not_public from returning all pages when no page restrictions exist (Mehrdad Moradizadeh)formfield_callback handling on ModelForm.Meta for future Django 4.2 release (Matt Westcott)ModelAdmin correctly supports filters in combination with subsequent searches without clearing the applied filters (Stefan Hammer)capitalize() calls to avoid issues with other languages or incorrectly presented model names for reporting and parts of site settings (Stefan Hammer)help_text for InlinePanel (Matt Westcott)for_user argument is passed to the form class when previewing pages (Matt Westcott)timesince_simple tag is consistently added in the template based on usage in context (Stefan Hammer)timesince_last_update and ensure the translated labels can be easier to work with in Transifex (Stefan Hammer)clean_name values in the Form Builder validation and increase performance of checks (Dan Bentley)wagtailsearch_editorspick table that prevents flushing the database (Matt Westcott)Update special-purpose FieldPanel deprecation message to add clarity for developers (Matt Westcott)
(Reissue of 4.0.3 due to packaging issues)
help_text when set on FieldPanel, MultiFieldPanel, FieldRowPanel, and other panel APIs where it previously worked without official support (Matt Westcott)FieldPanel deprecation message to add clarity for developers (Matt Westcott)help_text for InlinePanel (Matt Westcott)AbstractForm & AbstractEmailForm page models correctly pass the form to the preview context (Dan Bentley)Update special-purpose FieldPanel deprecation message to add clarity for developers (Matt Westcott)
help_text when set on FieldPanel, MultiFieldPanel, FieldRowPanel, and other panel APIs where it previously worked without official support (Matt Westcott)FieldPanel deprecation message to add clarity for developers (Matt Westcott)help_text for InlinePanel (Matt Westcott)AbstractForm & AbstractEmailForm page models correctly pass the form to the preview context (Dan Bentley)Update all images and sections of the Wagtail Editor's guide to align with the new admin interface changes from Wagtail 3.0 and 4.0 (Thibaud Colas)
DraftStateMixin applied (Sage Abdullah)FilterFieldError (Stefan Hammer)simple_translation app is installed (Dan Braghis)MultiFieldPanel correctly outputs all child classnames in the template (Matt Westcott)Fix: On the Locked Pages report, limit the "locked by" filter to just users who have locked pages (Stefan Hammer)
Deprecate the usage and documentation of the wagtail.contrib.modeladmin.menus.SubMenu class, provide a warning if used directing developers to use wag…
BaseGenericSetting base model class that allows defining a settings model that applies to all sites rather than just a single site (Kyle Bayliss)base_url_path to ModelAdmin so that the default URL structure of app_label/model_name can be overridden (Vu Pham, Khanh Hoang)full_url to the API output of ImageRenditionField (Paarth Agarwal)InlinePanel's label when available for field comparison label (Sandil Ranasinghe)FormData instead of jQuery's form.serialize when editing documents or images just added so that additional fields can be better supported (Stefan Hammer)PageRevision with generic Revision model (Sage Abdullah)wagtail.admin.views.generic (Matt Westcott)wagtail.admin.widgets.chooser.BaseChooser to make it easier to build custom chooser inputs (Matt Westcott)WAGTAIL_ENABLE_UPDATE_CHECK = 'lts' (Tibor Leupold)prefetch_renditions method to ImageQueryset for performance optimisation on image listings (Tidiane Dia, Karl Hobley)get_field_clean_name method when defining FormField models that extend AbstractFormField (LB (Ben) Johnston)core.css file (Thibaud Colas)ReportView to extend from generic wagtail.admin.views.generic.models.IndexView (Sage Abdullah)wagtail.admin.viewsets.chooser.ChooserViewSet module to serve as a common base implementation for chooser modals (Matt Westcott)wagtail.admin.viewsets.model.ModelViewSet (Matt Westcott)add_to_admin_menu option for ModelAdmin (Oliver Parker)Page.get_latest_revision_as_page to Page.get_latest_revision_as_object (Sage Abdullah)PermissionHelper (Tidiane Dia)get_snippet_edit_handler function to wagtail.admin.panels.get_edit_handler (Sage Abdullah)boost works when using Postgres with the database search backend (Tibor Leupold)explorer_breadcrumb template tag to breadcrumbs as it is now used in multiple locations (Paarth Agarwal)django-filter version to support 23 (Yuekui).iterator() in a few more places in the admin, to make it more stable on sites with many pages (Andy Babic)wagtail.contrib.modeladmin.menus.SubMenu class, provide a warning if used directing developers to use wagtail.admin.menu.Menu instead (Matt Westcott)ModelAdmin usage of breadcrumbs completely (Paarth Agarwal)WAGTAILADMIN_USER_PASSWORD_RESET_FORM setting for overriding the admin password reset form (Michael Karamuth)classnames template tag to easily build up classes from variables provided to a template (Paarth Agarwal)ModelAdmin InspectView footer actions consistent with other parts of the UI (Thibaud Colas)menu_item_name to modify MenuItem's name for ModelAdmin (Alexander Rogovskyy, Vu Pham)blocks_by_name and first_block_by_name methods on StreamValue (Tidiane Dia, Matt Westcott)SearchableListMixin (Sage Abdullah)is_parent kwarg in various page button hooks as this approach is no longer required (Paarth Agarwal)BadSignature error (Jaap Roes)range utility function (LB (Ben) Johnston)main id on main element (for skip link) and consistent DOM layout for h1 header (Paarth Agarwal, LB (Ben) Johnston)autofocus (LB (Ben) Johnston)path and re_path decorators to the RoutablePageMixin module which emulate their Django URL utils equivalent, redirect re_path to the original route decorator (Tidiane Dia)BaseChooser widget now provides a Telepath adapter that's directly usable for any subclasses that use the chooser widget and modal JS as-is with no customisations (Matt Westcott)ResumeWorkflowActionFormatter message (Stefan Hammer)ModelAdmin index listings with export list enabled would show buttons with an incorrect layout (Josh Woodcock)aria-label is not set on locale selection dropdown within page chooser modal as it was a duplicate of the button contents (LB (Ben Johnston))ModelAdmin title column behaviour to only link to 'edit' if the user has the correct permissions, fallback to the 'inspect' view or a non-clickable title if needed (Stefan Hammer)DecimalBlock preserves the Decimal type when retrieving from the database (Yves Serrano)ngettext in Wagtail's internal JavaScript internationalisation utilities now works (LB (Ben) Johnston)ModelAdmin single selection lists show correctly with Django 4.0 form template changes (Coen van der Kamp)AttributeError when an empty search param q= is combined with other filters in the Images index view (Paritosh Kabra)extra_actions in new changes to shared header template to avoid invalid template variable usage (Paarth Agarwal)BaseSiteSetting / BaseGenericSetting objects can be pickled (Andy Babic)DocumentChooserBlock can be deconstructed for migrations (Matt Westcott)BaseSetting when upgrading to Wagtail 4.0 (Stefan Hammer)updatemodulepaths command for Python 3.7 (Matt Westcott)Add missing icon file causing manage.py collectstatic to fail
Changes from 4.0rc1:
manage.py collectstatic to failget_preview_template and get_preview_context methodsDeprecate the usage and documentation of the wagtail.contrib.modeladmin.menus.SubMenu class, provide a warning if used directing developers to use wag…
BaseGenericSetting base model class that allows defining a settings model that applies to all sites rather than just a single site (Kyle Bayliss)base_url_path to ModelAdmin so that the default URL structure of app_label/model_name can be overridden (Vu Pham, Khanh Hoang)full_url to the API output of ImageRenditionField (Paarth Agarwal)ModelAdmin index listings with export list enabled would show buttons with an incorrect layout (Josh Woodcock)InlinePanel's label when available for field comparison label (Sandil Ranasinghe)FormData instead of jQuery's form.serialize when editing documents or images just added so that additional fields can be better supported (Stefan Hammer)PageRevision with generic Revision model (Sage Abdullah)wagtail.admin.views.generic (Matt Westcott)wagtail.admin.widgets.chooser.BaseChooser to make it easier to build custom chooser inputs (Matt Westcott)WAGTAIL_ENABLE_UPDATE_CHECK = 'lts' (Tibor Leupold)prefetch_renditions method to ImageQueryset for performance optimisation on image listings (Tidiane Dia, Karl Hobley)get_field_clean_name method when defining FormField models that extend AbstractFormField (LB (Ben) Johnston)core.css file (Thibaud Colas)ReportView to extend from generic wagtail.admin.views.generic.models.IndexView (Sage Abdullah)wagtail.admin.viewsets.chooser.ChooserViewSet module to serve as a common base implementation for chooser modals (Matt Westcott)wagtail.admin.viewsets.model.ModelViewSet (Matt Westcott)add_to_admin_menu option for ModelAdmin (Oliver Parker)Page.get_latest_revision_as_page to Page.get_latest_revision_as_object (Sage Abdullah)get_snippet_edit_handler function to wagtail.admin.panels.get_edit_handler (Sage Abdullah)boost works when using Postgres with the database search backend (Tibor Leupold)explorer_breadcrumb template tag to breadcrumbs as it is now used in multiple locations (Paarth Agarwal)django-filter version to support 23 (Yuekui).iterator() in a few more places in the admin, to make it more stable on sites with many pages (Andy Babic)wagtail.contrib.modeladmin.menus.SubMenu class, provide a warning if used directing developers to use wagtail.admin.menu.Menu instead (Matt Westcott)ModelAdmin usage of breadcrumbs completely (Paarth Agarwal)WAGTAILADMIN_USER_PASSWORD_RESET_FORM setting for overriding the admin password reset form (Michael Karamuth)classnames template tag to easily build up classes from variables provided to a template (Paarth Agarwal)menu_item_name to modify MenuItem's name for ModelAdmin (Alexander Rogovskyy, Vu Pham)blocks_by_name and first_block_by_name methods on StreamValue (Tidiane Dia, Matt Westcott)SearchableListMixin (Sage Abdullah)is_parent kwarg in various page button hooks as this approach is no longer required (Paarth Agarwal)BadSignature error (Jaap Roes)range util for (LB (Ben) Johnston)main id on main element (for skip link) and consistent DOM layout for h1 header (Paarth Agarwal, LB (Ben) Johnston)autofocus (LB (Ben) Johnston)path and re_path decorators to the RoutablePageMixin module which emulate their Django URL utils equivalent, redirect re_path to the original route decorator (Tidiane Dia)BaseChooser widget now provides a Telepath adapter that's directly usable for any subclasses that use the chooser widget and modal JS as-is with no customisations (Matt Westcott)ResumeWorkflowActionFormatter message (Stefan Hammer)aria-label is not set on locale selection dropdown within page chooser modal as it was a duplicate of the button contents (LB (Ben Johnston))ModelAdmin title column behaviour to only link to 'edit' if the user has the correct permissions, fallback to the 'inspect' view or a non-clickable title if needed (Stefan Hammer)DecimalBlock preserves the Decimal type when retrieving from the database (Yves Serrano)ngettext in Wagtail's internal JavaScript internationalisation utilities now works (LB (Ben) Johnston)AttributeError when an empty search param q= is combined with other filters in the Images index view (Paritosh Kabra)extra_actions in new changes to shared header template to avoid invalid template variable usage (Paarth Agarwal)BaseSiteSetting / BaseGenericSetting objects can be pickled (Andy Babic)Fix: On the Locked Pages report, limit the "locked by" filter to just users who have locked pages (Stefan Hammer)
Fix: Ensure string representation of FormSubmission returns a string (LB (Ben Johnston))
FormSubmission returns a string (LB (Ben Johnston))updatemodulepaths command for Python 3.7 (Matt Westcott)Add warning when WAGTAILADMIN_BASE_URL is not configured (Matt Westcott)
WAGTAILADMIN_BASE_URL is not configured (Matt Westcott)TabbedInterface will not show a tab if no panels are visible due to permissions (Paarth Agarwal)WAGTAIL_ENABLE_UPDATE_CHECK sends the referrer origin with strict-origin-when-cross-origin (Karl Hobley)WAGTAILADMIN_BASE_URL is absent due to the request object not being available (Matt Westcott)Phase out special-purpose panel types (StreamFieldPanel, RichTextFieldPanel, ImageChooserPanel, DocumentChooserPanel, PageChooserPanel, SnippetChooser
StreamFieldPanel, RichTextFieldPanel, ImageChooserPanel, DocumentChooserPanel, PageChooserPanel, SnippetChooserPanel) in favour of FieldPanel (Matt Westcott):focus-visible for cross-browser consistency (Paarth Agarwal)modelAdmin (Serafeim Papastefanos)README.md logo to work for GitHub dark mode (Paarth Agarwal)If-Modified-Since header in sendfile_streaming_backend which was only used by IE (Mariusz Felisiak)StreamField to use JSONField to store data, rather than TextField (Sage Abdullah)content_json TextField with content JSONField in PageRevision (Sage Abdullah)replace_text management command (Sage Abdullah)data_json TextField with data JSONField in BaseLogEntry (Sage Abdullah)page_description to the Page model, to provide help text for a given page type (Kalob Taulien, Thibaud Colas, Matt Westcott, Stefan Hammer)trimmed attribute to all blocktrans tags, so spacing is more reliable in translated strings (Harris Lapiroff)ModelAdmin to manage Tags (Abdulmajeed Isa)BASE_URL (undocumented) to WAGTAILADMIN_BASE_URL and add to documentation, BASE_URL will be removed in a future release (Sandil Ranasinghe)AbstractEmailForm (Jake Howard)WAGTAILIMAGES_RENDITION_STORAGE setting to allow an alternative image rendition storage (Heather White)wagtail_update_image_renditions management command to regenerate image renditions or purge all existing renditions (Hitansh Shah, Onno Timmerman, Damian Moore)PageQuerySet.specific() to reduce memory consumption (Andy Babic)TAG_SPACES_ALLOWED is True or False (Abdulmajeed Isa)AbstractFormSubmission's form_data to use JSONField to store form submissions (Jake Howard)simple_translations ensure that the user is redirected to the page edit view when submitting for a single locale (Mitchel Cabuloy)Form pages, ensure that all added fields are correctly shown in the preview (Joshua Munn)WAGTAILDOCS_CONTENT_TYPES & WAGTAILDOCS_INLINE_CONTENT_TYPES ensure that the filename is correctly set in the Content-Disposition header so that saving the files will use the correct filename (John-Scott Atlakson)aria-haspopup="menu" for all sidebar menu items that have sub-menus (LB (Ben Johnston))aria-expanded is always explicitly set as a string in sidebar (LB (Ben Johnston))role="main" attributes on <main> elements causing HTML validation issues (Luis Espinoza)lang attributes to <html> elements (James Ray)thumb_col_header_text is correctly used by ThumbnailMixin within ModelAdmin as the column header label (Kyle J. Roux)exclude_fields_in_copy (John-Scott Atlakson)IntegrityError when publishing pages with translatable Orderables that were copied without being published (Kalob Taulien, Dan Braghis)GenericRelation when copying pages (John-Scott Atlakson)wagtail updatemodulepaths works when system locale is not UTF-8 (Matt Westcott)STATIC_URL is not "/static/" (Jacob Topp-Mugglestone)Your coding agent can read these notes before it upgrades. Set up the MCP server →