docs/releases/6.0.md
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);