Wagtail 2.15 (LTS) release notes

November 4, 2021

Wagtail 2.15 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

New database search backend

Wagtail has a new search backend that uses the full-text search features of the database in use. It supports SQLite, PostgreSQL, MySQL, and MariaDB.

This new search backend replaces both the existing generic database and PostgreSQL-specific search backends.

To switch to this new backend, see the upgrade considerations below.

This feature was developed by Aldán Creo as part of Google Summer of Code.

Bulk actions

Bulk actions are now available for Page, User, Image, and Document models in the Wagtail Admin, allowing users to perform actions like publication or deletion on groups of objects at once.

This feature was developed by Shohan Dutta Roy, mentored by Dan Braghis, Jacob Topp-Mugglestone, and Storm Heg.

Audit logging for all models

Audit logging has been extended so that all models (not just pages) can have actions logged against them. The Site History report now includes logs from all object types and snippets and ModelAdmin provide a history view showing previous edits to an object. This feature was developed by Matt Westcott, and sponsored by The Motley Fool.

Collection management permissions

Permission for managing collections can now be assigned to individual subtrees of the collection hierarchy, allowing sub-teams within a site to control how their images and documents are organized. For more information, see Collection management permissions. This feature was developed by Cynthia Kiser.

Typed table block

A new TypedTableBlock block type is available for StreamField, allowing authors to create tables where the cell values are any StreamField block type, including rich text. For more information, see Typed table block. This feature was developed by Matt Westcott, Coen van der Kamp and Scott Cranfill, and sponsored by YouGov.

Windows high contrast support

As part of a broad push to improve the accessibility of the administration interface, Wagtail now supports Windows high contrast mode. There are remaining known issues but we are confident Wagtail is now much more usable for people relying on this assistive technology.

Individual fixes were implemented by a large number of first-time and seasoned contributors:

  • Comments icon now matches link color (Dmitrii Faiazov, LB (Ben Johnston))

  • Sidebar logo is now visible in high contrast mode (Dmitrii Faiazov, LB (Ben Johnston))

  • Icons in links and buttons now use the appropriate “active control” color (Dmitrii Faiazov, LB (Ben Johnston))

  • Comments dropdown now has a border (Shariq Jamil, LB (Ben Johnston))

  • Make StreamField block chooser menu buttons appear as buttons (Dmitrii Faiazov, LB (Ben Johnston))

  • Add a separator to identify the search forms (Dmitrii Faiazov, LB (Ben Johnston))

  • Update tab styles so the active tab can be identified (Dmitrii Faiazov, LB (Ben Johnston))

  • Make hamburger menu a button for tab and high contrast accessibility (Amy Chan, Dan Braghis)

  • Tag fields now have the correct background (Desai Akshata, LB (Ben Johnston))

  • Added sidebar vertical separation with main content (Onkar Apte, LB (Ben Johnston))

  • Added vertical separation between field panels (Chakita Muttaraju, LB (Ben Johnston))

  • Switch widgets on/off states are now visually distinguishable (Sakshi Uppoor, Thibaud Colas)

  • Checkbox widgets on/off states are now visually distinguishable (Thibaud Colas, Jacob Topp-Mugglestone, LB (Ben Johnston))

Particular thanks to LB, who reviewed almost all of those contributions, and Kyle Bayliss, who did the initial audit to identify High contrast mode issues.

Other features

  • Add the ability for the page chooser to convert external urls that match a page to internal links, see WAGTAILADMIN_EXTERNAL_LINK_CONVERSION (Jacob Topp-Mugglestone. Sponsored by The Motley Fool)

  • Added “Extending Wagtail” section to documentation (Matt Westcott)

  • Introduced template components, a standard mechanism for renderable objects in the admin (Matt Westcott)

  • Support min_num / max_num options on ListBlock (Matt Westcott)

  • Implemented automatic tree synchronisation for contrib.simple_translation (Mitchel Cabuloy)

  • Added a background_position_style property to renditions. This can be used to crop images using its focal point in the browser. See Setting the background-position inline style based on the focal point (Karl Hobley)

  • Added a distinct wagtail.copy_for_translation log action type (Karl Hobley)

  • Add a debug logger around image rendition generation (Jake Howard)

  • Convert Documents and Images to class based views for easier overriding (Matt Westcott)

  • Isolate admin URLs for Documents and Images search listing results with the name ‘listing_results’ (Matt Westcott)

  • Removed request.is_ajax() usage in Documents, Image and Snippet views (Matt Westcott)

  • Simplify generic admin view templates plus ensure page_title and page_subtitle are used consistently (Matt Westcott)

  • Extend support for collapsing edit panels from just MultiFieldPanels to all kinds of panels (Fabien Le Frapper, Robbie Mackay)

  • Add object count to header within modeladmin listing view (Jonathan “Yoni” Knoll)

  • Add ability to return HTML in multiple image upload errors (Gordon Pendleton)

  • Upgrade internal JS tooling; Node v14 plus other smaller package upgrades (LB (Ben Johnston))

  • Add support for non_field_errors rendering in Workflow action modal (LB (Ben Johnston))

  • Support calling get_image_model and get_document_model at import time (Matt Westcott)

  • When copying a page, default the ‘Publish copied page’ field to false (Justin Slay)

  • Open Preview and Live page links in the same tab, except where it would interrupt editing a Page (Sagar Agarwal)

  • Added ExcelDateFormatter to wagtail.admin.views.mixins so that dates in Excel exports will appear in the locale’s SHORT_DATETIME_FORMAT (Andrew Stone)

  • Add TIDAL support to the list of oEmbed providers (Wout De Puysseleir)

  • Add label_format attribute to customize the label shown for a collapsed StructBlock (Matt Westcott)

  • User Group permissions editing in the admin will now show all custom object permissions in one row instead of a separate table (Kamil Marut)

  • Create ImageFileMixin to extract shared file handling methods from AbstractImage and AbstractRendition (Fabien Le Frapper)

  • Add before_delete_page and register_permissions examples to Hooks documentation (Jane Liu, Daniel Fairhead)

  • Add clarity to modeladmin template override behavior in the documentation (Joe Howard, Dan Swain)

  • Add section about CSV exports to security documentation (Matt Westcott)

  • Add initial support for Django 4.0 deprecations (Matt Westcott, Jochen Wersdörfer)

  • Translations in nl_NL are moved to the nl po files. nl_NL translation files are deleted. Projects that use LANGUAGE_CODE = 'nl-nl' will automatically fallback to nl. (Loïc Teixeira, Coen van der Kamp)

  • Add documentation for how to redirect to a separate page on Form builder submissions using RoutablePageMixin (Nick Smith)

  • Refactored index listing views and made column sort-by headings more consistent (Matt Westcott)

  • The title field on Image and Document uploads will now default to the filename without the file extension and this behavior can be customized (LB Johnston)

  • Add support for Python 3.10 (Matt Westcott)

  • Introduce, autocomplete, a separate method which performs partial matching on specific autocomplete fields. This is useful for suggesting pages to the user in real-time as they type their query. (Karl Hobley, Matt Westcott)

  • Use SVG icons in modeladmin headers and StreamField buttons/headers (Jérôme Lebleu)

  • Add tags to existing Django registered checks (LB Johnston)

  • Upgrade admin frontend JS libraries jQuery to 3.6.0 (Fabien Le Frapper)

  • Added request.preview_mode so that template rendering can vary based on preview mode (Andy Chosak)

Bug fixes

  • Delete button is now correct colour on snippets and modeladmin listings (Brandon Murch)

  • Ensure that StreamBlock / ListBlock-level validation errors are counted towards error counts (Matt Westcott)

  • InlinePanel add button is now keyboard navigatable (Jesse Menn)

  • Remove redundant ‘clear’ button from site root page chooser (Matt Westcott)

  • Make ModelAdmin IndexView keyboard-navigable (Saptak Sengupta)

  • Prevent error on refreshing page previews when multiple preview tabs are open (Alex Tomkins)

  • Menu sidebar hamburger icon on smaller viewports now correctly indicates it is a button to screen readers and can be accessed via keyboard (Amy Chan, Dan Braghis)

  • blocks.MultipleChoiceBlock, forms.CheckboxSelectMultiple and ArrayField checkboxes will now stack instead of display inline to align with all other checkboxes fields (Seb Brown)

  • Screen readers can now access login screen field labels (Amy Chan)

  • Admin breadcrumbs home icon now shows for users with access to a subtree only (Stefan Hammer)

  • Add handling of invalid inline styles submitted to RichText so ConfigException is not thrown (Alex Tomkins)

  • Ensure comment notifications dropdown handles longer translations without overflowing content (Krzysztof Jeziorny)

  • Set default_auto_field in postgres_search AppConfig (Nick Moreton)

  • Ensure admin tab JS events are handled on page load (Andrew Stone)

  • EmailNotificationMixin and send_notification should only send emails to active users (Bryan Williams)

  • Disable Task confirmation now shows the correct value for quantity of tasks in progress (LB Johnston)

  • Page history now works correctly when it contains changes by a deleted user (Dan Braghis)

  • Add gettext_lazy to ModelAdmin built in view titles so that language settings are correctly used (Matt Westcott)

  • Tabbing and keyboard interaction on the Wagtail userbar now aligns with ARIA best practices (Storm Heg)

  • Add full support for custom edit_handler usage by adding missing bind_to call to PreviewOnEdit view (Stefan Hammer)

  • Only show active (not disabled) tasks in the workflow task chooser (LB Johnston)

  • CSS build scripts now output to the correct directory paths on Windows (Vince Salvino)

  • Capture log output from style fallback to avoid noise in unit tests (Matt Westcott)

  • Nested InlinePanel usage no longer fails to save when creating two or more items (Indresh P, Rinish Sam, Anirudh V S)

  • Changed relation name used for admin commenting from comments to wagtail_admin_comments to avoid conflicts with third-party commenting apps (Matt Westcott)

  • CSS variables are now correctly used for the filtering menu in modeladmin (Noah H)

  • Panel heading attribute is no longer ignored when nested inside a MultiFieldPanel (Jérôme Lebleu)

Upgrade considerations

Database search backends replaced

The following search backends (configured in WAGTAILSEARCH_BACKENDS) have been deprecated:

  • wagtail.search.backends.db (the default if WAGTAILSEARCH_BACKENDS is not specified)

  • wagtail.contrib.postgres_search.backend

Both of these backends have now been replaced by wagtail.search.backends.database. This new backend supports all of the features of the PostgreSQL backend, and also supports other databases. It will be made the default backend in Wagtail 3.0. To enable the new backend, edit (or add) the WAGTAILSEARCH_BACKENDS setting as follows:

    'default': {
        'BACKEND': 'wagtail.search.backends.database',

Also remove 'wagtail.contrib.postgres_search' from INSTALLED_APPS if this was previously set.

After switching to this backend, you will need to run the manage.py update_index management command to populate the search index (see update_index).

If you have used the PostgreSQL-specific SEARCH_CONFIG, this will continue to work as before with the new backend. For example:

    'default': {
        'BACKEND': 'wagtail.search.backends.database',
        'SEARCH_CONFIG': 'english',

However, as a PostgreSQL specific feature, this will be ignored when using a different database.

Admin homepage panels, summary items and action menu items now use components

Several Wagtail hooks provide a mechanism for passing Python objects to be rendered as HTML inside admin views, and the APIs for these objects have been updated to adopt a common template components pattern. The affected objects are:

User code that creates these objects should be updated to follow the component API. This will typically require the following changes:

  • Homepage panels should be made subclasses of wagtail.admin.ui.components.Component, and the render(self) method should be changed to render_html(self, parent_context). (Alternatively, rather than defining render_html, it may be more convenient to reimplement it with a template, as per Creating components.)

  • Summary item classes can continue to inherit from wagtail.admin.site_summary.SummaryItem (which is now a subclass of Component) as before, but:

    • Any template attribute should be changed to template_name;

    • Any place where the render(self) method is overridden should be changed to render_html(self, parent_context);

    • Any place where the get_context(self) method is overridden should be changed to get_context_data(self, parent_context).

  • Action menu items for pages and snippets can continue to inherit from wagtail.admin.action_menu.ActionMenuItem and wagtail.snippets.action_menu.ActionMenuItem respectively - these are now subclasses of Component - but:

    • Any template attribute should be changed to template_name;

    • Any get_context method should be renamed to get_context_data;

    • The get_url, is_shown, get_context_data and render_html methods no longer accept a request parameter. The request object is available in the context dictionary as context['request'].

Passing callables as messages in register_log_actions is deprecated

When defining new action types for audit logging with the register_log_actions hook, it was previously possible to pass a callable as the message. This is now deprecated - to define a message that depends on the log entry’s data, you should now create a subclass of wagtail.core.log_actions.LogFormatter. For example:

from django.utils.translation import gettext_lazy as _
from wagtail.core import hooks

def additional_log_actions(actions):

    def greeting_message(data):
        return _('Hello %(audience)s') % {
            'audience': data['audience'],
    actions.register_action('wagtail_package.greet_audience', _('Greet audience'), greeting_message)

should now be rewritten as:

from django.utils.translation import gettext_lazy as _
from wagtail.core import hooks
from wagtail.core.log_actions import LogFormatter

def additional_log_actions(actions):

    class GreetingActionFormatter(LogFormatter):
        label = _('Greet audience')

        def format_message(self, log_entry):
            return _('Hello %(audience)s') % {
                'audience': log_entry.data['audience'],

PageLogEntry.objects.log_action is deprecated

Audit logging is now supported on all model types, not just pages, and so the PageLogEntry.objects.log_action method for logging actions performed on pages is deprecated in favor of the general-purpose log function. Code that calls PageLogEntry.objects.log_action should now import the log function from wagtail.core.log_actions and call this instead (all arguments are unchanged).

Additionally, for logging actions on non-Page models, it is generally no longer necessary to subclass BaseLogEntry; see Audit log for further details.

Removed support for Internet Explorer (IE11)

If this affects you or your organization, consider which alternative browsers you may be able to use. Wagtail is fully compatible with Microsoft Edge, Microsoft’s replacement for Internet Explorer. You may consider using its IE mode to keep access to IE11-only sites, while other sites and apps like Wagtail can leverage modern browser capabilities.

search() method partial match future deprecation

Before the autocomplete() method was introduced, the search method also did partial matching. This behavior is will be deprecated in a future release and you should either switch to the new autocomplete() method or pass partial_match=False into the search method to opt-in to the new behavior. The partial matching in search() will be completely removed in a future release. See: Searching QuerySets

Change of relation name for admin comments

The related_name of the relation linking the Page and User models to admin comments has been changed from comments to wagtail_admin_comments, to avoid conflicts with third-party apps that implement commenting. If you have any code that references the comments relation (including fixture files), this should be updated to refer to wagtail_admin_comments instead. If this is not feasible, the previous behavior can be restored by adding WAGTAIL_COMMENTS_RELATION_NAME = 'comments' to your project’s settings.

Reusable library code that needs to preserve backwards compatibility with previous Wagtail versions can find out the relation name as follows:

    from wagtail.core.models import COMMENTS_RELATION_NAME
except ImportError:

Bulk action views not covered by existing hooks

Bulk action views provide alternative routes to actions like publishing or copying a page. If your site relies on hooks like before_publish_page or before_copy_page to perform checks, or add additional functionality, those hooks will not be called on the corresponding bulk action views. If you want to add this to the bulk action views as well, use the new bulk action hooks: before_bulk_action and after_bulk_action.