August 31, 2022
---
local:
depth: 1
---
This release adds support for Django 4.1.
The new BaseGenericSetting
base model class allows defining a settings model that applies to all sites rather than just a single site.
See the Settings documentation for more information. This feature was implemented by Kyle Bayliss.
When using a queryset to render a list of images, you can now use the prefetch_renditions()
queryset method to prefetch the renditions needed for rendering with a single extra query, similar to prefetch_related
. If you have many renditions per image, you can also call it with filters as arguments - prefetch_renditions("fill-700x586", "min-600x400")
- to fetch only the renditions you intend on using for a smaller query. For long lists of images, this can provide a significant boost to performance. See [](prefetching_image_renditions) for more examples. This feature was developed by Tidiane Dia and Karl Hobley.
Following from Wagtail 3.0, this release contains significant UI changes that affect all of Wagtail's admin, largely driven by the implementation of the new Page Editor. These include:
Further updates to the page editor are expected in the next release. Those changes were implemented by Thibaud Colas. Development on this feature was sponsored by Google.
As part of the page editor redesign project sponsored by Google, we have made a number of improvements to our rich text editor:
1.
to a list item. It’s now possible to un-do this change and keep the text as-is. This works for all Markdown-style shortcuts.Wagtail’s page preview is now available in a side panel within the page editor. This preview auto-updates as users type, and can display the page in three different viewports: mobile, tablet, desktop. The existing preview functionality is still present, moved inside the preview panel rather than at the bottom of the page editor. The auto-update delay can be configured with the WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL
setting. This feature was developed by Sage Abdullah.
In Wagtail 2.12, we introduced theming support for Wagtail’s primary brand colour. This has now been extended to almost all of Wagtail’s colour palette. View our [](custom_user_interface_colours) documentation for more information, an overview of Wagtail’s customisable colour palette, and a live demo of the supported customisations. This was implemented by Thibaud Colas, under the page editor redesign project sponsored by Google.
In Wagtail 2.16, we introduced support for Windows High Contrast mode (WHCM). This release sees a lot of improvements to our support, thanks to our new contributor Anuja Verma, who has been working on this as part of the Contrast Themes Google Summer of Code project, with support from Jane Hughes, Scott Cranfill, and Thibaud Colas.
In Wagtail 3.0, a new Page Editor experience was introduced, this release brings many of the UX and UI improvements to other parts of Wagtail for a more consistent experience. The bulk of these enhancements have been from Paarth Agarwal, who has been doing the UX Unification internship project alongside other Google Summer of Code participants. This internship has been sponsored by Torchbox with mentoring support from LB (Ben Johnston), Thibaud Colas and Helen Chapman.
autofocus
explorer_breadcrumb
template tag to breadcrumbs
as it is now used in multiple locationsModelAdmin
usage of breadcrumbs completely and adopt consistent 'back' link approachSnippets can now be given a previewable HTML representation, revision history, and draft / live states through the use of the mixins PreviewableMixin
, RevisionMixin
, and DraftStateMixin
. For more details, see:
These features were developed by Sage Abdullah.
The documentation now has dark mode which will be turned on by default if set in your browser or OS preferences, it can also be toggled on and off manually. The colours and fonts of the documentation now align with the design updates introduced in Wagtail 3.0. These features were developed by Vince Salvino.
There are also many improvements to the documentation both under the hood and in the layout;
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)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)Unpublish
view to extend from generic wagtail.admin.views.generic.models.UnpublishView
(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)PermissionHelper
(Tidiane Dia)boost
works when using Postgres with the database search backend (Tibor Leupold)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)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)is_parent
kwarg in various page button hooks as this approach is no longer required (Paarth Agarwal)BadSignature
error (Jaap Roes)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)ModelAdmin
index listings with export list enabled would show buttons with an incorrect layout (Josh Woodcock)ResumeWorkflowActionFormatter
message (Stefan Hammer)PageRevision
with generic Revision
model (Sage Abdullah)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)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)Page.serve()
and Page.serve_preview()
methodsAs part of making previews available to non-page models, the serve_preview()
method has been decoupled from the serve()
method and extracted into the PreviewableMixin
class. If you have overridden the serve()
method in your page models, you will likely need to override serve_preview()
, get_preview_template()
, and/or get_preview_context()
methods to handle previews accordingly. Alternatively, you can also override the preview_modes
property to return an empty list to disable previews.
The live preview panel utilises an iframe to display the preview in the editor page, which requires the page in the iframe to have the X-Frame-Options
header set to SAMEORIGIN
(or unset). If you click a link within the preview panel, you may notice that the iframe stops working. This is because the link is loaded within the iframe and the linked page may have the X-Frame-Options
header set to DENY
. To work around this problem, add the following <base>
tag within your <head>
element in your base.html
template, before any <link>
elements:
{% if request.in_preview_panel %}
<base target="_blank">
{% endif %}
This will make all links in the live preview panel open in a new tab.
As of Wagtail 4.0.1, new Wagtail projects created through the wagtail start
command already include this change in the base template.
base_url_path
keyword argument added to AdminURLHelperThe wagtail.contrib.modeladmin.helpers.AdminURLHelper
class now accepts a base_url_path
keyword argument on its constructor. Custom subclasses of this class should be updated to accept this keyword argument.
Safari 13 will no longer be officially supported as of this release, this deviates the current support for the last 3 version of Safari by a few months and was required to add better support for RTL languages.
PageRevision
replaced with Revision
The PageRevision
model has been replaced with a generic Revision
model. If you use the PageRevision
model in your code, make sure that:
PageRevision
objects should be updated to create Revision
objects using the page's id
as the object_id
, the default Page
model's content type as the base_content_type
, and the page's specific content type as the content_type
.PageRevision.objects
manager should be updated to use the Revision.page_revisions
manager.Revision
queries that use Page.id
should be updated to cast the Page.id
to a string before using it in the query (e.g. by using str()
or Cast("page_id", output_field=CharField())
).Page
queries that use PageRevision.page_id
should be updated to cast the Revision.object_id
to an integer before using it in the query (e.g. by using int()
or Cast("object_id", output_field=IntegerField())
).PageRevision.page
should be updated to Revision.content_object
.If you maintain a package across multiple Wagtail versions that includes a model with a ForeignKey
to the PageRevision
model, you can create a helper function to correctly resolve the model depending on the installed Wagtail version, for example:
from django.db import models
from wagtail import VERSION as WAGTAIL_VERSION
def get_revision_model():
if WAGTAIL_VERSION >= (4, 0):
return "wagtailcore.Revision"
return "wagtailcore.PageRevision"
class MyModel(models.Model):
# Before
# revision = models.ForeignKey("wagtailcore.PageRevision")
revision = models.ForeignKey(get_revision_model(), on_delete=models.CASCADE)
Page.get_latest_revision_as_page
renamed to Page.get_latest_revision_as_object
The Page.get_latest_revision_as_page
method has been renamed to Page.get_latest_revision_as_object
. The old name still exists for backwards-compatibility, but calling it will raise a RemovedInWagtail50Warning
.
AdminChooser
replaced with BaseChooser
Custom choosers should no longer use wagtail.admin.widgets.chooser.AdminChooser
which has been replaced with wagtail.admin.widgets.chooser.BaseChooser
.
get_snippet_edit_handler
moved to wagtail.admin.panels.get_edit_handler
The get_snippet_edit_handler
function in wagtail.snippets.views.snippets
has been moved to get_edit_handler
in wagtail.admin.panels
.
explorer_breadcrumb
template tag has been renamed to breadcrumbs
, move_breadcrumb
has been removedThe explorer_breadcrumb
template tag is not documented, however if used it will need to be renamed to breadcrumbs
and the url_name
is now a required arg.
The move_breadcrumb
template tag is no longer used and has been removed.
wagtail.contrib.modeladmin.menus.SubMenu
is deprecatedThe wagtail.contrib.modeladmin.menus.SubMenu
class should no longer be used for constructing submenus of the admin sidebar menu. Instead, import wagtail.admin.menu.Menu
and pass the list of menu items as the items
keyword argument.
The internal JavaScript functions createPageChooser
, createSnippetChooser
, createDocumentChooser
and createImageChooser
used for initialising chooser widgets have been replaced by classes, and user code that calls them needs to be updated accordingly:
createPageChooser(id)
should be replaced with new PageChooser(id)
createSnippetChooser(id)
should be replaced with new SnippetChooser(id)
createDocumentChooser(id)
should be replaced with new DocumentChooser(id)
createImageChooser(id)
should be replaced with new ImageChooser(id)
If your code contains references to URL route names within the wagtailimages
, wagtaildocs
or wagtailsnippets
namespaces, these should be updated as follows:
wagtailimages:chooser
is now wagtailimages_chooser:choose
wagtailimages:chooser_results
is now wagtailimages_chooser:choose_results
wagtailimages:image_chosen
is now wagtailimages_chooser:chosen
wagtailimages:chooser_upload
is now wagtailimages_chooser:create
wagtailimages:chooser_select_format
is now wagtailimages_chooser:select_format
wagtaildocs:chooser
is now wagtaildocs_chooser:choose
wagtaildocs:chooser_results
is now wagtaildocs_chooser:choose_results
wagtaildocs:document_chosen
is now wagtaildocs_chooser:chosen
wagtaildocs:chooser_upload
is now wagtaildocs_chooser:create
wagtailsnippets:list
, wagtailsnippets:list_results
, wagtailsnippets:add
, wagtailsnippets:edit
, wagtailsnippets:delete-multiple
, wagtailsnippets:delete
, wagtailsnippets:usage
, wagtailsnippets:history
: These now exist in a separate wagtailsnippets_{app_label}_{model_name}
namespace for each snippet model, and no longer take app_label
and model_name
as arguments.wagtailsnippets:choose
, wagtailsnippets:choose_results
, wagtailsnippets:chosen
: These now exist in a separate wagtailsnippetchoosers_{app_label}_{model_name}
namespace for each snippet model, and no longer take app_label
and model_name
as arguments.As part of the introduction of the new live preview panel, we have changed the WAGTAIL_AUTO_UPDATE_PREVIEW
setting to be on (True
) by default. This can still be turned off by setting it to False
. The WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL
setting has been introduced for sites willing to reduce the performance cost of the live preview without turning it off completely.
The page explorer listings now use Wagtail’s new slim header, replacing the previous large teal header. The parent page’s metadata and related actions are now available within the “Info” side panel, while the majority of buttons are now available under the Actions dropdown in the header, identically to the page create/edit forms.
Customising which actions are available and adding extra actions is still possible, but has to be done with the register_page_header_buttons
hook, rather than register_page_listing_buttons
and register_page_listing_more_buttons
. Those hooks still work as-is to define actions for each page within the listings.
is_parent
removed from page button hooksconstruct_page_listing_buttons
, register_page_listing_buttons
, register_page_listing_more_buttons
no longer accept the is_parent
keyword argument and this should be removed.is_parent
was the previous approach for determining whether the buttons would show in the listing rows or the page's more button, this can be now achieved with discrete hooks instead.As part of our support for theming across all colors, we’ve had to rename or remove some of the pre-existing CSS variables. Wagtail’s indigo is now customisable with --w-color-primary
, and the teal is customisable as --w-color-secondary
. See [](custom_user_interface_colours) for an overview of all customisable colours. Here are replaced variables:
--color-primary
is now --w-color-secondary
--color-primary-hue
is now --w-color-secondary-hue
--color-primary-saturation
is now --w-color-secondary-saturation
--color-primary-lightness
is now --w-color-secondary-lightness
--color-primary-darker
is now --w-color-secondary-400
--color-primary-darker-hue
is now --w-color-secondary-400-hue
--color-primary-darker-saturation
is now --w-color-secondary-400-saturation
--color-primary-darker-lightness
is now --w-color-secondary-400-lightness
--color-primary-dark
is now --w-color-secondary-600
--color-primary-dark-hue
is now --w-color-secondary-600-hue
--color-primary-dark-saturation
is now --w-color-secondary-600-saturation
--color-primary-dark-lightness
is now --w-color-secondary-600-lightness
--color-primary-lighter
is now --w-color-secondary-100
--color-primary-lighter-hue
is now --w-color-secondary-100-hue
--color-primary-lighter-saturation
is now --w-color-secondary-100-saturation
--color-primary-lighter-lightness
is now --w-color-secondary-100-lightness
--color-primary-light
is now --w-color-secondary-50
--color-primary-light-hue
is now --w-color-secondary-50-hue
--color-primary-light-saturation
is now --w-color-secondary-50-saturation
--color-primary-light-lightness
is now --w-color-secondary-50-lightness
We’ve additionally removed all --color-input-focus
and --color-input-focus-border
variables, as Wagtail’s form fields no longer have a different colour on focus.
WAGTAILDOCS_DOCUMENT_FORM_BASE
and WAGTAILIMAGES_IMAGE_FORM_BASE
must inherit from BaseDocumentForm
/ BaseImageForm
Previously, it was valid to specify an arbitrary model form as the WAGTAILDOCS_DOCUMENT_FORM_BASE
/ WAGTAILIMAGES_IMAGE_FORM_BASE
settings. This is no longer supported; these forms must now inherit from wagtail.documents.forms.BaseDocumentForm
and wagtail.images.forms.BaseImageForm
respectively.
As part of the page editor redesign, we have removed support for the classname="full"
customisation to panels. Existing title
and collapsed
customisations remain unchanged.
route
decorator for RoutablePageMixin
route
decorator at this time.RoutablePageMixin
contrib module now provides a path
decorator that behaves the same way as Django's django.urls.path
function.RoutablePageMixin
's route
decorator will now redirect to a new re_path
decorator that emulates the behaviour of django.urls.re_path
.BaseSetting
model replaced by BaseSiteSetting
The wagtail.contrib.settings.models.BaseSetting
model has been replaced by two new base models BaseSiteSetting
and BaseGenericSetting
, to accommodate settings that are shared across all sites. Existing setting models that inherit BaseSetting
should be updated to use BaseSiteSetting
instead:
from wagtail.contrib.settings.models import BaseSetting, register_setting
@register_setting
class SiteSpecificSocialMediaSettings(BaseSetting):
facebook = models.URLField()
should become
from wagtail.contrib.settings.models import BaseSiteSetting, register_setting
@register_setting
class SiteSpecificSocialMediaSettings(BaseSiteSetting):
facebook = models.URLField()