docs/releases/7.1.md
August 4, 2025
---
local:
depth: 1
---
Check out our upcoming Wagtail Space 2025 event 🚀! Online, ✨ free ✨, October 8-10.
The app now allows permission over site settings to be granted on a per-site basis. This makes it possible to give non-superuser accounts full control over the configuration of an individual site. This feature was developed by Matt Westcott.
The app now allows previews to be enabled for generic and site setting models through PreviewableMixin. This makes it possible to preview your site while editing the settings. For more details, see . This feature was developed by Sébastien Corbin and Sage Abdullah.
Image listings now support both grid and list layouts, with a simple toggle for users to switch between the two. The list layout gives you more information about the images, such as the file name, collection, creation date, and usage count. This helps CMS users manage larger collections of images, and makes it possible to display more metadata about images in the future.
The documents listing now also display the usage count for each document, making it easier to see which documents are being used on your site.
Thank you to Joel William for implementing this as part of the Google Summer of Code program, with support from Coen van der Kamp, Sage Abdullah, Thibaud Colas, Ben Enright.
To make it easier to navigate complex structured content, blocks created with StructBlock can now be collapsed and expanded like other structured block types. A common need for this is block settings, where the block supports a lot of optional fields:
class BlockQuote(StructBlock):
text = TextBlock()
attribute_name = CharBlock(blank=True, required=False, label="e.g. Mary Berry")
# Fields within the settings block will be available but hidden by default.
settings = ThemeSettingsBlock(collapsed=True)
For more information, see and . This feature was implemented by Sage Abdullah, with support from the Wagtail UI team.
The live preview and user bar features have been refactored and improved to work better in headless setups. The preview panel can now load a cross-domain headless frontend (provided by the wagtail-headless-preview package). The Wagtail user bar has been refactored into a template component, allowing it to be rendered independently and loaded by the headless frontend. Incorporating the user bar into the frontend enables features in the page editor, such as:
For more details, see the documentation on enabling the user bar and accessibility checker in headless setups. This feature was developed by Sage Abdullah.
Wagtail’s developer documentation now includes experimental docs to reuse client-side code and UI components. This new documentation helps developers reuse existing components when creating customizations or extensions of the admin interface, so those customizations are simpler to build and maintain. The documentation is experimental, as well as reuse of those UI components. This means a component's API may change in a minor release without going through the deprecation process. If you use these components in your own code, please ensure that you have a testing process in place to catch any breaking changes with each Wagtail upgrade.
This feature was implemented by Sage Abdullah, with support from the Wagtail UI team.
The admin interface now supports more keyboard shortcuts to facilitate common actions: in this release, toggling the main navigation sidebar, and the minimap within the page editor. It’s also now possible for users to disable all of Wagtail’s custom shortcuts via a dedicated setting in their user profile.
Thank you to Dhruvi Patel for implementing this as part of the Google Summer of Code program, with support from Scott Cranfill, Thibaud Colas, LB (Ben) Johnston.
The panels mechanism used by the page and snippet editing forms now provides an API for client-side code to access the panel structure. This makes it possible to retrieve and manipulate the form contents without navigating the HTML structure of the page, which is not guaranteed to remain stable across releases of Wagtail. For further information, see . This feature was developed by Matt Westcott.
NumberColumn to display numbers in universal listings (Baptiste Mispelon)GenericRelations for RevisionMixin and WorkflowMixin, to avoid issues with deletion cascades (Sage Abdullah)init_new_page signal (Maciek Baron)requests to access oEmbed endpoints, for more robust SSL certificate handling (Matt Westcott)RichTextBlock and RichTextField (Alec Baron)SnippetChooserBlock's icon to take precedence over SnippetViewSet.icon (Matt Westcott)preserve-svg in Jinja2 image tags (Vishesh Garg)preserve-svg as a filter when calling Image.get_rendition directly (Richard Allen)preserve-svg for Image.get_renditions, picture, and srcset_image tags (Matt Westcott)TypedTableBlock content when indexing for search (Charan T M)find view to the detail view (Andrew Hosgood)NoFutureDateValidator to validate against dates in the future (Talha Rizwan)background_position_x and background_position_y properties from AbstractRendition.background_position_style (Chiemezuo Akujobi)form_attrs support to all StreamField blocks (Sage Abdullah)label_format support for more widget types in StreamField (Sage Abdullah)preview_value and default in Block meta options as callables for dynamic previews within StreamField (Ziyao Yan, Sage Abdullah)preview_value for RichTextBlock (Seb Corbin)WAGTAILADMIN_LOGIN_URL is respected when logging out of the admin (Antoine Rodriguez, Ramon de Jezus)ViewSet.inject_view_methods with multiple methods (Gorlik)exclude_fields_in_copy (Matt Westcott)import_redirects command (Matt Westcott)first_published_at field are preserved on reloading (Talha Rizwan)BooleanColumn icons so they can be distinguished without relying on color (Sage Abdullah)django.middleware.security.SecurityMiddleware first (Brylie Christopher Oxley)help_text kwarg in FloatBlock (Nick Smith)aria-invalid on StreamField widgets input when there is an error (Sage Abdullah)human_readable_date template tag (Seb Corbin)order_by expressions in database search backends (Seb Corbin)avif in WAGTAILIMAGES_EXTENSIONS example (Thibaud Colas)data-edit-form and interacting with the editor form and preview panel (Sage Abdullah)get_embed to remove finder argument which was only used for mocking in unit tests (Jigyasu Rajput)None values in TypedTableBlock (Jigyasu Rajput)utf8mb4 charset and collation for MySQL test database (Sage Abdullah)django.contrib.postgres to test settings INSTALLED_APPS (Sage Abdullah)SlugController with more generic and reusable CleanController (LB (Ben) Johnston)/etc (LB (Ben) Johnston)EventTarget instead of events.EventEmitter from Webpack (Sage Abdullah)telepath/widgets.js into separate files (Matt Westcott)label_format behavior in StructBlockThe label_format option for StructBlock has been changed to always show the block's original label when the block is collapsed, with the label_format string shown after it as a summary instead of replacing the label. This means that if you had previously set label_format to include (or be the same as) the label, you would likely want to remove the original label's text from the label_format string.
PageListingButton, SnippetListingButton, and UserListingButtonThe PageListingButton, SnippetListingButton, and UserListingButton classes have been deprecated in favour of the generic ListingButton and Button classes.
The PageListingButton class was previously documented as part of the register_page_listing_buttons hook. If you used this hook to add buttons to the page listing, you should now replace wagtail.admin.widgets.PageListingButton with wagtail.admin.widgets.ListingButton. Using the PageListingButton class will continue to work for now, but will raise a deprecation warning.
The SnippetListingButton and UserListingButton classes were previously documented as part of the register_snippet_listing_buttons and register_user_listing_buttons hooks, respectively. If you used these hooks to add buttons to the snippet or user listing, you should now replace wagtail.snippets.widgets.SnippetListingButton and wagtail.users.widgets.UserListingButton with one of the following:
wagtail.admin.widgets.Button if you want the button to appear as an item inside the "More" actions dropdown in the listing.wagtail.admin.widgets.ListingButton if you want the button to appear as a top-level button in the listing.Using the SnippetListingButton or UserListingButton classes will continue to work for now, but will raise a deprecation warning.
The PageListingButton, SnippetListingButton, and UserListingButton classes will be removed in a future release.
ListingButton in IndexView.get_list_more_buttons now renders the button as a top-level buttonIf you have overridden the undocumented get_list_more_buttons method on a generic IndexView subclass (e.g. for a ModelViewSet) and used the ListingButton class to add buttons to the "More" actions dropdown, these buttons will now be rendered as top-level buttons in the listing. If you want the buttons to appear inside the "More" actions dropdown, you should use the Button class instead.
init_new_page moved to wagtail.signalsThe signal, previously defined in wagtail.admin.signals, has now been moved to wagtail.signals. Any import lines referencing the old location need to be updated.
AccessibilityItem now accepts an in_editor argumentThe AccessibilityItem user bar item now accepts an {attr}~wagtail.admin.userbar.AccessibilityItem.in_editor argument, which is set to True when it is instantiated within the page editor. If you customized the accessibility checker, you should update your code to pass this argument when creating an instance of your AccessibilityItem subclass.
@hooks.register('construct_wagtail_userbar')
def replace_userbar_accessibility_item(request, items, page):
items[:] = [
- CustomAccessibilityItem()
+ CustomAccessibilityItem(in_editor=item.in_editor)
if isinstance(item, AccessibilityItem) else item
for item in items
]
If you do not update your code, the AccessibilityItem will continue to work, but the in_editor argument will always be False. Wagtail does not currently use this argument, but it may do so in the future. It may also be utilized by users for cross-domain headless setups.
wagtail.telepath and wagtail.widget_adapters moved to wagtail.admin.telepathThe wagtail.telepath module has now been moved to wagtail.admin.telepath, and wagtail.widget_adapters has been moved to wagtail.admin.telepath.widgets. Any import lines referencing the old locations need to be updated.
The wagtailimages listing view templates have been adapted to support both list and grid layout. Those adaptations should be replicated for any overrides or reuse of those templates.
wagtailadmin/js/telepath/telepath.jsThe JavaScript file wagtailadmin/js/telepath/telepath.js is no longer required, as Telepath initialization is now handled within wagtailadmin/js/core.js. Any templates used within the Wagtail admin should remove imports of this file; any front-end code using Telepath outside of the Wagtail admin should use the telepath.js supplied with the telepath package or telepath-unpack.
The frontend implementation of the Tabs component (used in TabbedInterface and elsewhere) has been rewritten using Stimulus.
Any existing usage of the component via the data-tabs attribute will no longer work. Here is a summary of the new approach.
These are subject to change and are still not officially documented, please add a thumbs up or comment to the feature request if you would like a formalised Python or JavaScript API for the Tabs component.
| Item | Usage | Old | New |
|---|---|---|---|
| Attribute | Root tab container div | data-tabs | data-controller="w-tabs" |
| Attribute | Tab trigger (tab) | role="tab" only | role="tab" & data-w-tabs-target="trigger" data-action="w-tabs#select:prevent" |
| Attribute | Non-tab ad-hoc triggers (as a link) | href="#tab-label-id" data-trigger | href="#the-tab-id" data-w-tabs-target="trigger" data-action="w-tabs#select:prevent" data-w-tabs-focus-param="true" (focus is optional, but recommended) |
| Attribute | Non-tab ad-hoc triggers (as a button) | N/A - was not supported | type="button" data-w-tabs-target="trigger" data-action="w-tabs#select" data-w-tabs-id-param="the-tab-id" data-w-tabs-focus-param="true" (focus is optional, but recommended) |
| Attribute | Opt in/out of URL sync, on tabs container | data-tabs-disable-url (opt out) | data-action="popstate@window->w-tabs#select" data-w-tabs-use-location-value="true" (opt in) |
| Attribute | Add a class when a panel becomes active | data-tabs-animate (hard-coded 'animate-in' class) | data-w-tabs-active-class="animate-in" |
| Attribute | Tab panel (content) | role="tabpanel" only | role="tabpanel" & data-w-tabs-target="panel" |
| Attribute | Tablist container keyboard control | role="tablist" | role="tablist" & data-action="keydown.right->w-tabs#selectNext keydown.left->w-tabs#selectPrevious keydown.home->w-tabs#selectFirst keydown.end->w-tabs#selectLast" |
| Event | A tab is selected | 'switch' (dispatched on the role=tablist, does not bubble) | 'w-tabs:selected' (dispatched on the triggers for the tab, does bubble) |
| Event | A change to the active panel | 'wagtail:tab-changed' (dispatched on document, does not bubble) | 'w-tabs:changed' (dispatched on the tabs container, does bubble) |
For a full HTML example, install the and see the tabs examples there.