Wagtail 7.0 (LTS) release notes¶
May 6, 2025
Wagtail 7.0 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).
What’s new¶
Django 5.2 support¶
This version adds formal support for Django 5.2.
Deferring validation on saving drafts¶
This release introduces a change to the validation behavior when saving pages (or snippets using DraftStateMixin
) as drafts. In most cases, required fields will not be enforced when saving as draft, allowing users to save work-in-progress versions without filling in all fields. Validation is applied as normal when the page or snippet is published, scheduled, or submitted to a workflow. The new behavior is enabled by default, but see the notes below on Configuring deferred validation of required fields.
This feature was developed by Matt Westcott and Sage Abdullah.
New and improved pagination¶
We have a new pagination interface for all listing views and most choosers, including page numbers. This simplifies navigation for listings with tens or hundreds of pages, so users can jump directly to the last pages. Thank you to Jordan Teichmann for implementing the new designs, with guidance from Sage Abdullah.
Locale in listings and choosers¶
This release adds a new “Locale” column to the listings and choosers of translatable models, making it easier to filter and sort by locale. The current content’s locale is applied in choosers by default, with the ability to clear the locale filter. This feature was developed by Dan Braghis and Sage Abdullah.
How-to guide for Django Ninja¶
While Wagtail provides a built-in API module based on the popular Django REST Framework, it is possible to use other approaches. This release adds a new How to set up Django Ninja guide, to demonstrate basic usage of Wagtail with Django Ninja, which leverages type hints and Pydantic for data validation. The guide covers common requirements beyond initial setup, like rich text, image renditions, and generation of API documentation.
This documentation was contributed by Thibaud Colas with support from Sage Abdullah.
Other features¶
Add
WAGTAIL_
prefix to Wagtail-specific tag settings (Aayushman Singh)Implement
normalize
onTypedTableBlock
to assist with settingdefault
andpreview_value
(Sage Abdullah)Apply normalization when modifying a
StreamBlock
’s value to assist with programmatic changes toStreamField
(Matt Westcott)Allow a custom image rendition model to define its unique constraint with
models.UniqueConstraint
instead ofunique_together
(Oliver Parker, Cynthia Kiser, Sage Abdullah)Default to the
standard
tokenizer on Elasticsearch, to correctly handle numbers as tokens (Matt Westcott)Add color-scheme meta tag to Wagtail admin (Ashish Nagmoti)
Add the ability to set the default privacy restriction for new pages using
get_default_privacy_setting
(Shlomo Markowitz)Improve performance of batch purging page urls in the frontend cache, avoiding n+1 query issues (Andy Babic)
Add better support and documentation for overriding or extending icons used in the in the userbar (Sébastien Corbin)
List the comments action, if comments are enabled, within the admin keyboard shortcuts dialog (Dhruvi Patel)
Add better support and documentation for overriding the default field widgets used within form pages (Baptiste Mispelon)
Allow workflow tasks to specify a template for the action modal via
get_template_for_action
(Sage Abdullah)Change ‘Publish’ button label to ‘Schedule to publish’ if go-live schedule is set (Sage Abdullah)
Hide add locale button when no more languages are available (Dan Braghis)
Allow customizing
InspectView
field display value via methods on the view (Dan Braghis)Make rendering of active listing filters extensible, to support additional filter types (Sage Abdullah)
Bug fixes¶
Take preferred language into account for translatable strings in client-side code (Bernhard Bliem, Sage Abdullah)
Support translating with the preferred language for rich text formatting labels (Bernhard Bliem, Sage Abdullah)
Make “Actions” label translatable within the rich text toolbar (Bernhard Bliem, Sage Abdullah)
Do not show the content type column as sortable when searching pages (Srishti Jaiswal, Sage Abdullah)
Support simple subqueries for
in
andexact
lookup on Elasticsearch (Sage Abdullah)Force preview panel scroll behavior to instant to avoid flickering (Sage Abdullah)
Fix incorrect “Views (past week)” heading on promoted search results listing (Baptiste Mispelon)
Ensure
InlinePanel
will be correctly ordered after the first save whenmin_num
is used (Elhussein Almasri, Joel William)Avoid deprecation warnings about URLField
assume_scheme
on Django 5.x (Sage Abdullah)Fix setup.cfg syntax for setuptools v78 (Sage Abdullah)
Ensure
ImproperlyConfigured
is thrown fromdb_field
on unboundFieldPanel
s as intended (Matt Westcott)Refine the positioning of the add comment button next to select, radio, checkbox fields and between field row columns (Srishti Jaiswal)
Show the correct privacy status for child collections of private collections (Shlomo Markowitz)
Ensure reference index correctly handles models with primary keys not named
id
(Sage Abdullah)On “move page” bulk action, do not prefill the destination with the root page (Stefan Hammer)
Ensure the default preferred language respects the
WAGTAILADMIN_PERMITTED_LANGUAGES
setting (Sébastien Corbin)Ensure there is consistent padding in homepage panels table headers (Aditya (megatrron))
Prevent redundant calls to context processors when rendering userbar (Ihor Marhitych)
Fix validation of duplicate field names in form builder when fields have been deleted (Ian Meigh)
Fix font size of footer action buttons when there is only one item (Sage Abdullah)
Documentation¶
Add missing
django.contrib.admin
to list of apps in “add to Django project” guide (Mohamed Rabiaa)Add tutorial on deploying on Ubuntu to third-party tutorials (Mohammad Fathi Rahman)
Document that
request_or_site
is optional onBaseGenericSetting.load
(Matt Westcott)Mention third-party
StreamField
based form builder packages in the form builder documentation (Matt Westcott)Clarify that
insert_editor_js
hook applies to all core editing/creation views (LB (Ben) Johnston)Clarify requirement for non-page models using model mixins to be registered as snippets (Sage Abdullah)
Document the
page.move
method from django-treebeard (Shlomo Markowitz)Clarify that
Page.get_url_parts
will return a tuple, notNone
forNoReverseMatch
errors (Arthur Tripp)Document the
expand_db_html
utility function to create HTML ready for display (Thibaud Colas)Mention
expand_db_html
usage for rich text in REST framework API (Thibaud Colas)Docs: Further document usage of API
?limit
withWAGTAILAPI_LIMIT_MAX
(Thibaud Colas)
Maintenance¶
Migrate away from deprecated Sass import rules to module system (Srishti Jaiswal)
Apply Sass mixed declarations migration in preparation for CSS nesting (Prabhpreet Kaur)
Refactor styles for Draftail, minimap, and comments to fix remaining Sass migration warnings (Thibaud Colas)
npm package updates;
downshift
,focus-trap-react
,immer
,redux
,uuid
(LB (Ben) Johnston)Validate against invalid characters in Lexeme values (Matt Westcott)
Split up
wagtail.models
module into submodules (Matt Westcott)Update
ruff
to 0.9.6 (Sage Abdullah)Fix up
stubs
&adapter
contents to better support Jest testing (LB (Ben) Johnston)Cleanup Stimulus controller imports, JSDoc & linting (LB (Ben) Johnston)
Rename
SkipLinkController
toFocusController
with improved reusability, updated unit tests, and added story (LB (Ben) Johnston)Fix CI testing issues with the Stimulus
LocaleController
time zones & non-deterministic page ordering tests (Sage Abdullah)Make GitHub highlight
.html
files as Django templates (Jake Howard)Remove admin JavaScript imports from shared template includes, moving the imports to the appropriate core admin inclusion locations (Sai Srikar Dumpeti)
Remove non-editing view inclusions of the
insert_editor_js
hook output, deprecate the wrapper template tag_editor_js.html
(Sai Srikar Dumpeti, LB (Ben) Johnston)Remove upper bound on Django dependency (Matt Westcott)
Add
default_auto_field
setting to home app in project template (Sylvain Boissel)Migrate setuptools configuration from
setup.py
andsetup.cfg
topyproject.toml
(Sage Abdullah)Refactor
move_choose_destination
to a class-based view (Chiemezuo Akujobi)Update
django-tasks
to 0.7.x (Jake Howard)
Upgrade considerations - removal of deprecated features from Wagtail 5.2 - 6.3¶
Features previously deprecated in Wagtail 5.2, 6.0, 6.1, 6.2 and 6.3 have been fully removed. For additional details on these changes, see:
The most significant changes are highlighted below.
Renamed settings¶
The
WAGTAIL_AUTO_UPDATE_PREVIEW
setting is removed and should be replaced withWAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL = 0
to disable auto-update.The
PASSWORD_REQUIRED_TEMPLATE
setting is no longer recognized and should be replaced withWAGTAIL_PASSWORD_REQUIRED_TEMPLATE
.The
DOCUMENT_PASSWORD_REQUIRED_TEMPLATE
setting is no longer recognized and should be replaced withWAGTAILDOCS_PASSWORD_REQUIRED_TEMPLATE
.
Replaced mechanism for customizing user form classes¶
The settings WAGTAIL_USER_EDIT_FORM
, WAGTAIL_USER_CREATION_FORM
and WAGTAIL_USER_CUSTOM_FIELDS
have been removed in favor of customizing the form classes via UserViewSet.get_form_class()
.
Other removals¶
The
get_template
method on StreamField blocks now accepts avalue
argument as its first argument.Passing a dict as
DISTRIBUTION_ID
within theWAGTAILFRONTENDCACHE
configuration setting is no longer supported, and should be replaced by multiple backends with aHOSTNAMES
parameter.ModelViewSet
no longer provides the URL patterns<int:pk>/
and<int:pk>/delete/
for editing and deleting; these have been replaced byedit/<str:pk>/
anddelete/<str:pk>/
.The undocumented usage of the JavaScript
window.chooserUrls
within Draftail choosers is removed.The undocumented
coreutils.escape_script
function andescapescript
template tag, and handling of<script type="text/django-form-template">
elements, are removed.The undocumented template tags
js_translation_strings
,locales
anduser_listing_buttons
are removed.The following undocumented global Javascript functions are removed:
window.initBlockWidget
,window.enableDirtyFormCheck
,window.URLify
,window.ActivateWorkflowActionsForDashboard
,window.ActivateWorkflowActionsForEditView
.The undocumented JavaScript variable
window.wagtailConfig.BULK_ACTION_ITEM_TYPE
is removed.Support for the
data-tippy-content
attribute is removed.The undocumented
DeleteMenuItem
API is removed.
Upgrade considerations - changes affecting all projects¶
Configuring deferred validation of required fields¶
For text-based fields (such as CharField
, TextField
, RichTextField
and StreamField
), the new behaviour of skipping required field validation on saving drafts is in place automatically, with no code changes required. For non-text-based fields (such as IntegerField
and DateField
) that are not defined with null=True
, the database will not allow saving of blank values, and so the form will continue to enforce these as required fields even when saving as draft.
To allow a non-text-based field to be left blank on saving drafts, add null=True
to its definition. The blank
argument specifies whether the field is required on publish, and should be omitted (or set to blank=False
) unless you intend the field to be fully optional. For example, the definition:
date_published = models.DateField("Date article published")
can be changed as follows to allow it to be left blank when saving as draft:
date_published = models.DateField("Date article published", null=True)
To strictly enforce requiredness on a field, including when saving as draft, you can set the attribute required_on_save = True
on the model field, or pass required_on_save=True
as an argument to FieldPanel
. For example:
subtitle = models.CharField(max_length=255)
subtitle.required_on_save = True
or
content_panels = Page.content_panels + [
FieldPanel("subtitle", required_on_save=True)
]
This option is enabled as standard for the title
field of page models. It is also recommended to use this option for any fields that are used in the __str__
representation of snippet models, so that these models always have a meaningful representation within listing views.
Page.save()
no longer automatically calls full_clean
for draft pages¶
In previous releases, the save()
method on page models called the full_clean
method to apply model-level validation rules, regardless of whether the page was in a draft or live state, unless this was explicitly disabled by passing clean=False
. As of this release, saving a page in a draft state (live=False
) will only perform the minimum validation necessary to ensure data integrity: the title must be non-empty, and the slug must be unique within the parent page. Saving a page with live=True
will apply full validation as before. If you have user code that creates draft pages and requires them to be validated, you must now call full_clean
explicitly.
Upgrade considerations - deprecation of old functionality¶
TAG_LIMIT
and TAG_SPACES_ALLOWED
settings renamed to WAGTAIL_TAG_LIMIT
and WAGTAIL_TAG_SPACES_ALLOWED
¶
The TAG_LIMIT
and TAG_SPACES_ALLOWED
settings have been renamed to WAGTAIL_TAG_LIMIT
and WAGTAIL_TAG_SPACES_ALLOWED
respectively. The old settings will continue to work for now, but will be removed in a future release.
Upgrade considerations - changes to undocumented internals¶
Removal of insert_editor_js
hook output in some non-editor views¶
The insert_editor_js
was historically added to some non editing views, these have now been removed.
The confirm bulk move view and the chooser modal view for choosing the new location of bulk move pages will no longer use the hook output insert_editor_js
. If custom JavaScript is needed in these views, migrate to the documented insert_global_admin_js hook instead.
The insert_editor_js
hook will continue to be output when editing pages, as documented.
Deprecation of wagtailadmin/pages/_editor_js.html
template¶
The undocumented template partial wagtailadmin/pages/_editor_js.html
has been deprecated and will be removed in a future release.
If your project overrides the template to inject custom JavaScript into the Wagtail admin, you should follow the documented approaches to either use the insert_editor_js hook or the insert_global_admin_js hook instead.