On deleting a page, image, document or snippet, the confirmation screen now provides a summary of where the object is used, allowing users to see the effect that deletion will have elsewhere on the site. This also prevents objects from being deleted in cases where deletion would be blocked by an `on_delete=PROTECT` constraint. This feature was developed by Sage Abdullah.
Support for adding custom validation logic to StreamField blocks has been formalised and simplified. For most purposes, raising a `ValidationError` from the block's `clean` method is now sufficient; more complex behaviours (such as attaching errors to a specific child block) are possible through block-specific subclasses of `ValidationError`. For more details, see [](streamfield_validation). This feature was developed by Matt Westcott.
* Ensure selected collection is kept when navigating from documents or images listings to add multiple views & upon upload (Aman Pandey, Bojan Mihelac)
* Remove confusing `SettingsPanel` reference in the page editing `TabbedInterface` example as `SettingsPanel` no longer shows anything as of 4.1 (Kenny Wolf, Julian Bigler)
The following features deprecated in Wagtail 3.0 have been fully removed. See [Wagtail 3.0 release notes](/releases/3.0) for details on these changes, including how to remove usage of these features:
* The modules `wagtail.core`, `wagtail.tests`, `wagtail.admin.edit_handlers` and `wagtail.contrib.forms.edit_handlers` are removed.
* The field panel classes `StreamFieldPanel`, `RichTextFieldPanel`, `ImageChooserPanel`, `DocumentChooserPanel` and `SnippetChooserPanel` are removed.
* The `ModelAdmin.get_form_fields_exclude` method is no longer passed a `request` argument.
* The `ModelAdmin.get_edit_handler` method is no longer passed a `request` or `instance` argument.
* The `widget_overrides`, `required_fields`, `required_formsets`, `bind_to`, `render_as_object` and `render_as_field` methods on `Panel` (previously `EditHandler`) are removed.
The following features deprecated in Wagtail 4.0 have been fully removed. See [Wagtail 4.0 release notes](/releases/4.0) for details on these changes, including how to remove usage of these features:
* The `wagtail.contrib.settings.models.BaseSetting` class is removed.
* The `Page.get_latest_revision_as_page` method is removed.
* The `page` and `page_id` properties and `as_page_object` method on `Revision` are removed.
* The JavaScript functions `createPageChooser`, `createSnippetChooser`, `createDocumentChooser` and `createImageChooser` are removed.
* The `wagtail.contrib.modeladmin.menus.SubMenu` class is removed.
* Subclasses of `wagtail.contrib.modeladmin.helpers.AdminURLHelper` are now required to accept a `base_url_path` keyword argument on the constructor.
* The `wagtail.admin.widgets.chooser.AdminChooser` class is removed.
* The `wagtail.snippets.views.snippets.get_snippet_edit_handler` function is removed.
The undocumented `Page.get_static_site_paths` method (which returns a generator of URL paths for use by static site generator packages) has been removed. Packages relying on this functionality should provide their own fallback implementation.
### `wagtailsearch.Query` has moved to `wagtail.contrib.search_promotions`
The `wagtailsearch.Query` model has been moved from the `search` application to the contrib application `wagtail.contrib.search_promotions`.
All imports will need to be updated and migrations will need to be run via a custom command, some imports will still work with a warning until a future version.
#### Migration command
If you have daily hits records in the `wagtailsearch.Query` you can run the management command to move these records to the new location.
### Changes to header CSS classes in `ModelAdmin` templates
If there are custom styles in place for the `ModelAdmin`'s header content or more complex [template overrides](modeladmin_overriding_templates) in us, there are a few changes for the following classes to be aware of.
### Slug field widget required for auto-formatting
The slug field JavaScript behaviour was previously attached to any field with an ID of `id_slug`, this has now changed to be any field with the appropriate HTML data attributes.
If using a custom edit handler or set of panels for page models, the correct widget will now need to be used for these data attributes to be included. This widget will use the `WAGTAIL_ALLOW_UNICODE_SLUGS` Django setting.
```python
from wagtail.admin.widgets.slug import SlugInput
# ... other imports
class MyPage(Page):
promote_panels = [
FieldPanel("slug", widget=SlugInput),
# ... other panels
]
```
Additionally, the slug behaviour can be attached to any field easily by including the following attributes in HTML or via Django's widget `attrs`.
### Progress button (`button-longrunning`) now implemented with Stimulus
The `button-longrunning` class usage has been updated to use the newly adopted Stimulus approach, the previous data attributes will be deprecated in a future release.
If using the old approach, ensure any HTML templates are updated to the new approach before the next major release.
Stimulus [targets](https://stimulus.hotwired.dev/reference/targets) and [actions](https://stimulus.hotwired.dev/reference/actions) can be leveraged to revise the behaviour via data attributes.
*`<button ... data-w-progress-duration-value="500" ...>` - custom duration can be declared on the element
*`<button ... class="custom-button" data-w-progress-active-class="custom-button--busy" ...>` - custom 'active' class to replace the default `button-longrunning-active` (must be a single string without spaces)
*`<button ... ><strong data-w-progress-target="label">{% trans 'Create' %}</strong></button>` - any element can be the button label (not just `em`)
*`<button ... data-action="w-progress#activate focus->w-progress#activate" ...>` - any event can be used to trigger the in progress behaviour
*`<button ... data-action="w-progress#activate:once" ...>` - only trigger the progress behaviour once
*`<button ... data-action="readystatechange@document->w-progress#activate:once" data-w-progress-duration-value="5000" disabled ...>` - disabled on load (once JS starts) and becomes enabled after 5s duration
### JavaScript `window.addMessages` replaced with event dispatching
The undocumented `window.addMessage` function is no longer available and will throw an error if called, if similar functionality is required use DOM Event dispatching instead as follows.
```js
// old
window.addMessage('success', 'Content has updated');
```
```js
// new
document.dispatchEvent(
new CustomEvent('w-messages:add', {
detail: { text: 'Content has updated', type: 'success' },
}),
);
// new (clearing existing messages before adding a new one)
document.dispatchEvent(
new CustomEvent('w-messages:add', {
detail: {
clear: true,
text: 'All content has updated',
type: 'success',
},
}),
);
// message types 'success', 'error', 'warning' are supported
```
Note that this event name may change in the future and this functionality is still not officially supported.
The client-side handling of StreamField validation errors has been updated. The JavaScript classes `StreamBlockValidationError`, `ListBlockValidationError`, `StructBlockValidationError` and `TypedTableBlockValidationError` have been removed, and the corresponding Python classes can no longer be serialised using Telepath. Instead, the `setError` methods on client-side block objects now accept a plain JSON representation of the error, obtained from the `as_json_data` method on the Python class. Custom JavaScript code that works with these objects must be updated accordingly.
Additionally, the Python `StreamBlockValidationError`, `ListBlockValidationError`, `StructBlockValidationError` and `TypedTableBlockValidationError` classes no longer provide a `params` dict with `block_errors` and `non_block_errors` items; these are now available as the attributes `block_errors` and `non_block_errors` on the exception itself (or `cell_errors` and `non_block_errors` in the case of `TypedTableBlockValidationError`).
The ability to remove multiple snippet instances from the `DeleteView` and the undocumented `wagtailsnippets_{app_label}_{model_name}:delete-multiple` URL pattern have been removed. The view's functionality has been replaced by the delete action of the bulk actions feature introduced in Wagtail 4.0.
The delete bulk action view now also calls the `{before,after}_delete_snippet` hooks, in addition to the `{before,after}_bulk_action` hooks.
If you have customised the `IndexView` and/or `DeleteView` views in a `SnippetViewSet` subclass, make sure that the `delete_multiple_url_name` attribute is renamed to `delete_url_name`.