Data from reports, form submissions and ModelAdmin can now be exported to both XLSX and CSV format. For ModelAdmin, this is enabled by specifying a ``list_export`` attribute on the ModelAdmin class. This feature was developed by Jacob Topp-Mugglestone and sponsored by `The Motley Fool <https://www.fool.com/>`_.
This release addresses a potential timing attack on pages or documents that have been protected with a shared password through Wagtail's "Privacy" controls. This password check is performed through a character-by-character string comparison, and so an attacker who is able to measure the time taken by this check to a high degree of accuracy could potentially use timing differences to gain knowledge of the password. (This is `understood to be feasible on a local network, but not on the public internet <https://groups.google.com/d/msg/django-developers/iAaq0pvHXuA/fpUuwjK3i2wJ>`_.)
Many thanks to Thibaud Colas for reporting this issue.
* ChoiceBlock now accepts a ``widget`` keyword argument (James O'Toole)
* Reduced contrast of rich text toolbar (Jack Paine)
* Support the rel attribute on custom ModelAdmin buttons (Andy Chosak)
* Server-side page slug generation now respects ``WAGTAIL_ALLOW_UNICODE_SLUGS`` (Arkadiusz Michał Ryś)
* Wagtail admin no longer depends on SiteMiddleware, avoiding incompatibility with Django sites framework and redundant database queries (aritas1, timmysmalls, Matt Westcott)
* Tag field autocompletion now handles custom tag models (Matt Westcott)
*``wagtail_serve`` URL route can now be omitted for headless sites (Storm Heg)
* Allow free tagging to be disabled on custom tag models (Matt Westcott)
* Allow disabling page preview by setting ``preview_modes`` to an empty list (Casper Timmers)
* Add Vidyard to oEmbed provider list (Steve Lyall)
* Optimise compiling media definitions for complex StreamBlocks (pimarc)
* FieldPanel now accepts a 'heading' argument (Jacob Topp-Mugglestone)
Wagtail's :class:`~wagtail.core.middleware.SiteMiddleware`, which makes the current site object available as the property ``request.site``, is now deprecated as it clashes with Django's sites framework and makes unnecessary database queries on non-Wagtail views. References to ``request.site`` in your code should be removed; the recommended way of retrieving the current site is ``Site.find_for_request(request)`` in Python code, and the ``{% wagtail_site %}`` tag within Django templates.
For `consistency with standard Django models <https://docs.djangoproject.com/en/stable/topics/db/queries/#deleting-objects>`_, the ``delete()`` method is no longer available on the default Page and Collection managers. Code such as ``Page.objects.delete()`` should be changed to ``Page.objects.all().delete()``.