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).
![Updated page explorer design, showing a search for "bread" with a slimmed-down results listing](../_static/images/releasenotes_5_2_page-explorer.png)
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](https://opensearch.org/) is now formally supported as an alternative to Elasticsearch. For configuration details, see [OpenSearch configuration](opensearch). This feature was developed by Matt Westcott.
### Responsive & multi-format images with the picture tag
Wagtail has new template tags to reduce the performance and environmental footprint of images:
* The `picture` tag generates images in multiple formats and-or sizes in one batch, creating an HTML `<picture>` tag.
* The `srcset_image` tag generates images in multiple sizes, creating an `<img>` tag with a `srcset` attribute.
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 [](multiple_formats) and [](responsive_images). Those new template tags are also supported in Jinja templates, see [](jinja2) 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](https://www.thegreenwebfoundation.org/news/working-with-the-wagtail-community-on-the-summer-of-code/) 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](image_file_formats) in Wagtail 5.1, Andy Babic for creating [`AbstractImage.get_renditions()`](image_renditions_multiple) in the same release; and Storm Heg, Mitchel Cabuloy, Coen van der Kamp, Tom Dyson, and Chris Lawton for their feedback on [RFC 71](https://github.com/wagtail/rfcs/pull/71).
### Support extending Wagtail client-side with Stimulus
Wagtail now officially supports client-side admin customisations with [Stimulus](https://stimulus.hotwired.dev/). The developer documentation has a dedicated page about [](extending_client_side). This covers fundamental topics of client-side extensibility, such as:
* Adding custom JavaScript
* Extending with DOM events and Wagtail's custom DOM events
Thank you to core contributor LB (Ben) Johnston for writing this documentation.
### `ModelViewSet` improvements
A number of 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.
* Move `SnippetViewSet` menu registration mechanism to base `ViewSet` class (Sage Abdullah)
* Move `SnippetViewSet` template override mechanism to `ModelViewSet` (Sage Abdullah)
* Move `SnippetViewSet.list_display` to `ModelViewSet` (Sage Abdullah)
* Move `list_filter`, `filterset_class`, `search_fields`, `search_backend_name`, `list_export`, `export_filename`, `list_per_page`, and `ordering` from `SnippetViewSet` to `ModelViewSet` (Sage Abdullah)
* Add default header titles to generic `IndexView` and `CreateView` (Sage Abdullah)
* Add the ability to use filters and to export listings in generic `IndexView` (Sage Abdullah)
* Add generic `UsageView` to `ModelViewSet` (Sage Abdullah)
* Add generic `InspectView` to `ModelViewSet` (Sage Abdullah)
* Extract generic `HistoryView` from snippets and add it to `ModelViewSet` (Sage Abdullah)
* Extract generic breadcrumbs functionality from page breadcrumbs (Sage Abdullah)
* Add breadcrumbs support to custom `ModelViewSet` views (Sage Abdullah)
* Allow `ModelViewSet` to be used with models that have non-integer primary keys (Sage Abdullah)
* Enable reference index tracking for models registered with `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`.
* Allow overriding `IndexView.export_headings` via `ModelViewSet` (Christer Jensen, Sage Abdullah)
* Add the ability to define listing buttons on generic `IndexView` (Sage Abdullah)
### User interface refinements
Several tweaks have been made to the admin user interface which we hope will make it easier to use.
* Show the full first published at date within a tooltip on the Page status sidebar on the relative date (Rohit Sharma)
* Do not render minimap if there are no panel anchors (Sage Abdullah)
* Use dropdown buttons on listings in dashboard panels (Sage Abdullah)
* Add support for Shift + Click behaviour in form submissions and simple translations submissions (LB (Ben) Johnston)
* Improve filtering of audit logging based on the user's permissions (Stefan Hammer)
### External links in promoted search results
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.
* Add [`wagtailcache`](wagtailcache) and [`wagtailpagecache`](wagtailpagecache) template tags to ensure previewing Pages or Snippets will not be cached (Jake Howard)
* Add [`linked_fields` mechanism on chooser widgets](chooser_viewsets_limiting_choices) to allow choices to be limited by fields on the calling page (Matt Westcott)
* Allow subclasses of `PagesAPIViewSet` override default [Page model via the `model`](api_v2_configure_endpoints) attribute (Neeraj Yetheendran, Herbert Poul)
* Increase the read buffer size to improve efficiency and performance when generating file hashes for document or image uploads, use `hashlib.file_digest` if available (Python 3.11+) (Jake Howard)
* The [`purge_revisions` management command](purge_revisions) 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)
* Filter out comments on Page editing counts that do not correspond to a valid field / block path on the page such as when a field has been removed (Matt Westcott)
* Ensure the panel title for a user's settings correctly reflects the `WAGTAIL_EMAIL_MANAGEMENT_ENABLED` setting by not showing 'email' if disabled (Omkar Jadhav)
* Document `WAGTAILADMIN_BASE_URL` on ["Integrating Wagtail into a Django project"](/getting_started/integrating_into_django) page (Shreshth Srivastava)
As part of our [adoption of Stimulus](https://github.com/wagtail/rfcs/blob/main/text/078-adopt-stimulus-js.md), in addition to the new documentation, we have migrated a number of existing components to the framework. Thank you to our core contributor LB who oversees this project, and to all contributors who refactored specific components.
* Migrate form submission listing checkbox toggling to the shared `w-bulk` Stimulus implementation (LB (Ben) Johnston)
* Migrate the editor unsaved messages popup to be driven by Stimulus using the shared `w-message` controller (LB (Ben) Johnston, Hussain Saherwala)
* Migrate all other `data-tippy` HTML attribute usage to the Stimulus data-*-value attributes for w-tooltip & w-dropdown (Subhajit Ghosh, LB (Ben) Johnston)
* Migrate select all on focus/click behavior to Stimulus, used on the image URL generator (Chiemezuo Akujobi)
* Add support for a `reset` method to support Stimulus driven dynamic field resets via the `w-action` controller (Chiemezuo Akujobi)
* Add support for a `notify` target on the Stimulus dialog for dispatching events internally (Chiemezuo Akujobi)
* Migrate publishing schedule dialog field resets to Stimulus (Chiemezuo Akujobi)
* Replace `<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)
* Add better deprecation warnings to the `search.Query`&`search.QueryDailyHits` model, move final set of templates from the admin search module to the search promotions contrib module (LB (Ben) Johnston)
### Adoption of `classname` convention for `MenuItem` related classes and hooks
Wagtail `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.MenuItem`
-`admin.ui.sidebar.ActionMenuItem`
-`admin.ui.sidebar.LinkMenuItem`
-`admin.ui.sidebar.PageExplorerMenuItem`
-`contrib.settings.registry.SettingMenuItem`
The following hooks usage may be impacted if `classnames` were used when generating menu items.
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 [](./2.10) for more details.
As a result, the following features are now deprecated:
If 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.
### Edit and delete URLs in `ModelViewSet` changed to allow non-integer primary keys
To 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:
- The edit URL pattern has been changed from `<int:pk>/` to `edit/<str:pk>/`
- The delete URL pattern has been changed from `<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 index
Models 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 [](managing_the_reference_index).
### Groups `IndexView.results_template_name` renamed from `results.html` to `index_results.html`
The `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 customised or extended the template, e.g. for [](customising_group_views), you will need to rename it to match the new name.
### Snippets templates refactored to reuse the shared `slim_header.html` template
The templates for the snippets views have been refactored to reuse the shared `slim_header.html` template. If you have customised or extended the templates, e.g. for [](wagtailsnippets_custom_admin_views), you will need to update them to match the new structure. As a result, the following templates have been removed:
In 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 removed
The `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`](django:topics/forms/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:
```python
from wagtail.admin.ui.side_panels import PageSidePanels
### `construct_snippet_listing_buttons` hook no longer accepts a `context` argument
The [`construct_snippet_listing_buttons`](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 customise 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.
### Hooks for page listing and page header buttons no longer accept a `page_perms` argument
The arguments passed to the hooks [`register_page_header_buttons`](register_page_header_buttons), [`register_page_listing_buttons`](register_page_listing_buttons), [`construct_page_listing_buttons`](construct_page_listing_buttons) and [`register_page_listing_more_buttons`](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)`.
*`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.
### Breadcrumbs now use different data attributes and events
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 behaviour may be impacted.
### `window.updateFooterSaveWarning` global util removed
The undocumented global util `window.updateFooterSaveWarning` has been removed, this is part of the footer 'unsaved' messages toggling behaviour on page forms.
This behaviour 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.
Use the HTML [`template`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template) element to avoid content from being parsed by the browser on load.
### Adoption of `classname` convention within the Image `Format` instance
When 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.
```python
# image_formats.py
from django.utils.html import format_html
from wagtail.images.formats import Format, register_image_format
#### Deprecated `search_garbage_collect` management command has been removed
In 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`](searchpromotions_garbage_collect).
The old command has now been fully removed and if called will throw an error.
#### Changes to URL names and templates
Some search promotions URLs and templates have now moved from the main admin search module into the search promotions module.
### `Block.get_template` now accepts a `value` argument
The `get_template` method on StreamField blocks now accepts a `value` argument in addition to `context`. Code using the old signature should be updated: