docs/releases/6.4.md
February 3, 2025
---
local:
depth: 1
---
django-tasksWagtail now integrates with the django-tasks library to allow moving computationally-intensive tasks out of the request-response cycle, and improving the performance of the Wagtail admin interface. These tasks include:
In the default configuration, these tasks are executed immediately within the request-response cycle, as they were in previous versions of Wagtail. However, by configuring the TASKS setting with an appropriate backend as per the django-tasks documentation, these tasks can be deferred to a background worker process.
This feature was developed by Jake Howard.
You can now set up previews for StreamField blocks. The preview will be shown in the block picker, along with a description for the block. This feature can help users choose the right block when writing content inside a StreamField. To enable this feature, see .
This feature was developed by Sage Abdullah and Thibaud Colas.
The new documentation page curates important information about Wagtail’s headless capabilities, directly within the developer documentation. This is the foundation for a headless improvements roadmap for Wagtail.
Thank you to Sævar Öfjörð Magnússon and Alex Fulcher for creating this new page at the Wagtail Space NL 2024 sprint.
Building upon improvements in past versions, this release comes with further enhancements to alt text management:
ImageBlock alt text is now populated from the image’s default alt text when selecting a new image.ImageBlock alt text field is also populated from the image’s default alt text when converting from an ImageChooserBlock.alt-text-quality content check.Thank you to Matt Westcott, Thibaud Colas, and Cynthia Kiser for their work on these improvements.
FieldPanel and InlinePanelPlain strings can now be used in panel definitions as a substitute for FieldPanel and InlinePanel, avoiding the need to import these classes from wagtail.admin.panels:
class MyPage(Page):
body = RichTextField()
content_panels = [
'body',
]
This feature was developed by Matt Westcott.
The StreamField and InlinePanel interfaces now support drag-and-drop reordering of items within a field. This makes it faster to rearrange content within these fields, particularly when there is a lot of content.
This feature was developed by Thibaud Colas and Sage Abdullah, thanks to a sponsorship by Lyst.
For users of promoted search results, a new search terms report is available in the admin interface. This report shows terms that website users have searched for, and how many times they have been searched. This can help you understand what your users are looking for, and adjust your search promotions accordingly.
This feature was developed by Noah van der Meer and Sage Abdullah.
Following from a recent audit, this release comes with performance improvements focused on the user interface.
specific() sub-queries using select_related & prefetch_related, see (Andy Babic)DATA_UPLOAD_MAX_NUMBER_FIELDS in project template (Matt Westcott)allowed_http_methods (Andy Babic)on_serve_page hook to modify the serving chain of pages (Krystian Magdziarz, Dawid Bugajewski)WAGTAIL_GRAVATAR_PROVIDER_URL URLs with query string parameters (Ayaan Qadri, Guilhem Saurel)get_avatar_url hook to customise user avatars (James Harrington)page as a third parameter to the construct_wagtail_userbar hook (claudobahn)Fuzzy queries (Tom Usher)StreamField.get_default() to prevent creation forms from breaking (Matt Westcott)read_only FieldPanels in use (Strapchay)th (table heading) elements that are not compliant with accessibility standards (Jai Vignesh J)MultipleChooserPanel using images or documents work when nested within an InlinePanel when no other choosers are in use within the model (Elhussein Almasri)MultipleChooserPanel works after doing a search in the page chooser modal (Matt Westcott)ListBlock instances get created with unique IDs in the admin client for accessibility and mini-map element references (Srishti Jaiswal)get_block_by_content_path on ImageBlock to prevent errors on commenting (Matt Westcott)aria-expanded attribute to new column button on TypedTableBlock to reflect menu state (Ayaan Qadri, Scott Cranfill)Page panel definitions without importing wagtail.admin (Matt Westcott)WidgetWithScript by raising it with stacklevel=3 (Joren Hammudoglu)FilterField("created_at") to AbstractDocument to fix ordering by created_at after searching in the documents index view (Srishti Jaiswal)Site.find_for_request() from Page.get_url_parts() (Andy Babic)StreamChildrenToListBlockOperation from duplicating data across multiple StreamField instances (Joshua Munn)wagtail start command to the management commands reference page (Damilola Oladele)DATA_UPLOAD_MAX_NUMBER_FIELDS when integrating Wagtail into Django (Matt Westcott)mark_safe to format_html for any script inclusions, to better avoid XSS issues from example code (Aayushman Singh)AbstractEmailForm or AbstractForm pages (John-Scott Atlakson, LB (Ben) Johnston)BlogTagIndexPage example for clarity (Clifford Gama)wagtailcache and wagtailpagecache examples to not use quotes for the fragment_name (Shiv)HTTPMethod in Page.handle_options_request() docs (Sage Abdullah)FieldPanel / InlinePanel where appropriate (Unyime Emmanuel Udoh)get_template method on StreamField blocks (Matt Westcott)RichTextBlock to a StreamField (Matt Westcott)ALLOWED_HOSTS check in Site.find_for_request (Jake Howard)CloneController to ensure that added/cleared events are not dispatched as cancelable (LB (Ben) Johnston)uuid UMD module as all code is now using the NPM module (LB (Ben) Johnston)eslint-disable no-undef linter directives with global comments (LB (Ben) Johnston)PreviewController usage to leverage Stimulus actions instead of calling preventDefault manually (Ayaan Qadri)ZoneController (w-zone) to support dynamic class name changes & event handling on container elements (Ayaan Qadri)ZoneController usage (Ayaan Qadri)ModalWorkflow (LB (Ben) Johnston)delay value in TagController to debounce async autocomplete tag fetch requests (Aayushman Singh)DrilldownController (Srishti Jaiswal)LinkController (w-link) (Sage Abdullah)EditView to make better use of generic EditView (Sage Abdullah)RulesController (w-rules) to support declarative conditional field enabling from other field values in a form (LB (Ben) Johnston)RulesController (w-rules) approach (LB (Ben) Johnston)ZoneController (w-zone) to support inactive class and a mechanism to switch the mode based on data within events (Ayaan Qadri)ZoneController (w-zone) to remove ad-hoc jQuery for the privacy switch when toggling visibility of private/public elements (Ayaan Qadri)is_active & active_menu_items from wagtail.admin.menu.MenuItem (Srishti Jaiswal)openpyxl at runtime to improve performance for projects that do not use ReportView, SpreadsheetExportMixin and wagtail.contrib.redirects (Sébastien Corbin)mp instead of mm for 'mystery person' as the default Gravatar if no avatar found (Harsh Dange)venv instead of pipenv in CircleCI (Sage Abdullah)FormsetController (w-formset) to support dynamic formset insertion/deletion behavior (LB (Ben) Johnston)revisions_revert view to be a subclass of EditView (Sage Abdullah)get_usage().count() call to view code (Sage Abdullah)DATA_UPLOAD_MAX_NUMBER_FIELDS updateIt's recommended that all projects set the DATA_UPLOAD_MAX_NUMBER_FIELDS setting to 10000 or higher.
This specifies the maximum number of fields allowed in a form submission, and it is recommended to increase this from Django's default of 1000, as particularly complex page models can exceed this limit within Wagtail's page editor:
# settings.py
DATA_UPLOAD_MAX_NUMBER_FIELDS = 10_000
related_nameOn previous releases, form page models (defined through AbstractEmailForm, AbstractForm, FormMixin or EmailFormMixin) did not validate form fields where the related_name was different to the default value of form_fields. As a result, it was possible to create forms with duplicate field names - in this case, only a single field is displayed and captured in the resulting form.
In this new release, validation is now applied on these fields, existing forms will continue to behave as before and no data will be lost. However, editing them will now raise a validation error and users may need to delete any duplicated fields that they had previously missed.
The behaviour described here no longer applies as of `django-tasks` 0.10. Tasks are now enqueued immediately (and executed immediately if `ImmediateBackend` is in use), and the `ENQUEUE_ON_COMMIT` setting is no longer available.
In the default configuration, tasks managed by django-tasks (see above) run during the request-response cycle, as before. However, they are now deferred until the current transaction (if any) is committed. If ATOMIC_REQUESTS is set to True, this will be at the end of the request. This may lead to a change of behaviour on views that expect to see the results of these tasks immediately, such as a view that creates a page and then performs a search query to retrieve it. To restore the previous behaviour, set "ENQUEUE_ON_COMMIT": False in the TASKS setting:
# settings.py
TASKS = {
"default": {
"BACKEND": "django_tasks.backends.immediate.ImmediateBackend",
"ENQUEUE_ON_COMMIT": False,
}
}
Django's test framework typically runs tests inside transactions, and so this situation is also likely to arise in tests that perform database updates and then - within the same test - expect these changes to be immediately reflected in search queries, object usage counts, and other processes that are now handled with background tasks. This can be addressed by setting ENQUEUE_ON_COMMIT to False as above in the test settings, or by wrapping the database updates in with self.captureOnCommitCallbacks(execute=True) to ensure that these tasks are completed before the test continues:
def test_search(self):
home_page = Page.objects.get(slug="home")
with self.captureOnCommitCallbacks(execute=True): # Added
home_page.add_child(instance=EventPage(title="Christmas party"))
response = self.client.get("/search/?q=Christmas")
self.assertContains(response, "Christmas party")
page as a third parameter to the construct_wagtail_userbar hookIn previous releases, implementations of the construct_wagtail_userbar hook were expected to accept two arguments, whereas now page is passed in as a third argument.
Old
@hooks.register('construct_wagtail_userbar')
def construct_wagtail_userbar(request, items):
pass
New
@hooks.register('construct_wagtail_userbar')
def construct_wagtail_userbar(request, items, page):
pass
The old style will now produce a deprecation warning.
content_panels, promote_panels and settings_panels values on base Page modelPreviously, the content_panels, promote_panels and settings_panels attributes on the base Page model were defined as lists of Panel instances. These lists now contain instances of wagtail.models.PanelPlaceholder instead, which are resolved to Panel instances at runtime. Panel definitions that simply extend these lists (such as content_panels = Page.content_panels + [...]) are unaffected; however, any logic that inspects these lists (for example, finding a panel in the list to insert a new one immediately after it) will need to be updated to handle the new object types.
The unused JavaScript include wagtailadmin/js/vendor/rangy-core.js has been removed from the editor interface, and functions such as window.rangy.getSelection() are no longer available. Any code relying on this should now either supply its own copy of the Rangy library, or be migrated to the official Document.createRange() browser API.
window.buildExpandingFormset global functionThe undocumented global function window.buildExpandingFormset to attach JavaScript insertion / deletion behavior for Django formsets has been deprecated and will be removed in a future release.
Within the Wagtail admin this only impacts a small set of basic expanding formsets in use across Workflow and Group view editing. InlinePanel is not affected.
Previously these expanding formsets required a mix of specific id attribute structures and inline scripts to instantiate with callbacks for handling deletion. User code implementing this functionality through buildExpandingFormset should be updated - the following data attributes can be used to emulate the same behavior. These are likely to change and should not be considered official documentation.
| Element | Attribute(s) |
|---|---|
| Containing element | data-controller="w-formset" |
| Element to append new child forms | data-w-formset-target="forms" |
| Child form element | data-w-formset-target="child" |
| Deleted form element | data-w-formset-target="deleted" hidden |
template element for blank form | data-w-formset-target="template" |
| Management field (total forms) | data-w-formset-target="totalFormsInput" |
| Management field (min forms) | data-w-formset-target="minFormsInput" |
| Management field (max forms) | data-w-formset-target="maxFormsInput" |
| Management field (Delete, within child form) | data-w-formset-target="deleteInput" |
Add child button | data-action="w-formset#add" |
Delete child button (within child form) | data-action="w-formset#delete" |
Usage of nested id structures are no longer required but can be left in place for easier debugging.