wagtail/docs/releases/6.2.md

13 KiB

Wagtail 6.2 release notes - IN DEVELOPMENT

Unreleased

---
local:
depth: 1
---

What's new

Alt text accessibility check

The built-in accessibility checker now enforces a new alt-text-quality rule, which tests alt text for the presence of known bad patterns such as file extensions. This rule is enabled by default, but can be disabled if necessary.

This feature was implemented by Albina Starykova, with support from the Wagtail accessibility team.

Other features

  • Optimize and consolidate redirects report view into the index view (Jake Howard, Dan Braghis)
  • Support a HOSTNAMES parameter on WAGTAILFRONTENDCACHE to define which hostnames a backend should respond to (Jake Howard, sponsored by Oxfam America)
  • Refactor redirects edit view to use the generic EditView and breadcrumbs (Rohit Sharma)
  • Allow custom permission policies on snippets to prevent superusers from creating or editing them (Sage Abdullah)
  • Do not link to edit view from listing views if user has no permission to edit (Sage Abdullah)
  • Allow access to snippets and other model viewsets to users with "View" permission (Sage Abdullah)
  • Skip ChooseParentView if only one possible valid parent page availale (Matthias Brück)
  • Add copy_for_translation_done signal when a page is copied for translation (Arnar Tumi Þorsteinsson)
  • Remove reduced opacity for draft page title in listings (Inju Michorius)
  • Adopt more compact representation for StreamField definitions in migrations (Matt Westcott)
  • Implement a new design for locale labels in listings (Albina Starykova)
  • Add a deactivate() method to ProgressController (Alex Morega)
  • Allow manually specifying credentials for CloudFront frontend cache backend (Jake Howard)
  • Automatically register permissions for models registered with a ModelViewSet (Sage Abdullah)
  • Implement universal listings UI for report views (Sage Abdullah)

Bug fixes

  • Make WAGTAILIMAGES_CHOOSER_PAGE_SIZE setting functional again (Rohit Sharma)
  • Enable richtext template tag to convert lazy translation values (Benjamin Bach)
  • Ensure permission labels on group permissions page are translated where available (Matt Westcott)
  • Preserve whitespace in comment replies (Elhussein Almasri)
  • Address layout issues in the title cell of universal listings (Sage Abdullah)
  • Support SVG icon id attributes with single quotes in the styleguide (Sage Abdullah)
  • Do not show delete button on model edit views if per-instance permissions prevent deletion (Matt Westcott)
  • Remove duplicate header in privacy dialog when a privacy setting is set on a parent page or collection (Matthias Brück)
  • Allow renditions of .ico images (Julie Rymer)
  • Fix the rendering of grouped choices when using ChoiceFilter in combination with choices (Sébastien Corbin)
  • Add separators when displaying multiple error messages on a StructBlock (Kyle Bayliss)
  • Specify verbose_name on TranslatableMixin.locale so that it is translated when used as a label (Romein van Buren)
  • Disallow null characters in API filter values (Jochen Wersdörfer)
  • Fix image preview when Willow optimizers are enabled (Alex Tomkins)
  • Ensure external-to-internal link conversion works when the wagtail_serve view is on a non-root path (Sage Abdullah)
  • Add missing for_instance method to PageLogEntryManager (Matt Westcott)
  • Ensure that "User" column on history view is translatable (Romein van Buren)

Documentation

  • Remove duplicate section on frontend caching proxies from performance page (Jake Howard)
  • Document restriction_type field on PageViewRestriction (Shlomo Markowitz)
  • Document Wagtail's bug bounty policy (Jake Howard)
  • Fix incorrect Sphinx-style code references to use MyST style (Byron Peebles)
  • Document the fact that Orderable is not required for inline panels (Bojan Mihelac)
  • Add note about prefers-reduced-motion to the accessibility documentation (Roel Koper)
  • Update deployment instructions for Fly.io (Jeroen de Vries)

Maintenance

  • Use DjangoJSONEncoder instead of custom LazyStringEncoder to serialize Draftail config (Sage Abdullah)
  • Refactor image chooser pagination to check WAGTAILIMAGES_CHOOSER_PAGE_SIZE at runtime (Matt Westcott)
  • Exclude the client/scss directory in Tailwind content config to speed up CSS compilation (Sage Abdullah)
  • Split contrib.frontend_cache.backends into dedicated sub-modules (Andy Babic)
  • Remove unused docs/autobuild.sh script (Sævar Öfjörð Magnússon)
  • Replace urlparse with urlsplit to improve performance (Jake Howard)
  • Optimise embed finder lookups (Jake Howard)

Upgrade considerations - changes affecting all projects

Specifying a dict of distribution IDs for CloudFront cache invalidation is deprecated

Previous versions allowed passing a dict for DISTRIBUTION_ID within the WAGTAILFRONTENDCACHE configuration for a CloudFront backend, to allow specifying different distribution IDs for different hostnames. This is now deprecated; instead, multiple distribution IDs should be defined as multiple backends, with a HOSTNAMES parameter to define the hostnames associated with each one. For example, a configuration such as:

WAGTAILFRONTENDCACHE = {
    'cloudfront': {
        'BACKEND': 'wagtail.contrib.frontend_cache.backends.CloudfrontBackend',
        'DISTRIBUTION_ID': {
            'www.wagtail.org': 'your-distribution-id',
            'www.madewithwagtail.org': 'other-distribution-id',
        },
    },
}

should now be rewritten as:

WAGTAILFRONTENDCACHE = {
    'mainsite': {
        'BACKEND': 'wagtail.contrib.frontend_cache.backends.CloudfrontBackend',
        'DISTRIBUTION_ID': 'your-distribution-id',
        'HOSTNAMES': ['www.wagtail.org'],
    },
    'madewithwagtail': {
        'BACKEND': 'wagtail.contrib.frontend_cache.backends.CloudfrontBackend',
        'DISTRIBUTION_ID': 'other-distribution-id',
        'HOSTNAMES': ['www.madewithwagtail.org'],
    },
}

Changes to permissions registration for models with ModelViewSet and SnippetViewSet

Models registered with a ModelViewSet will now automatically have their {class}~django.contrib.auth.models.Permission objects registered in the Groups administration area. Previously, you need to use the register_permissions hook to register them.

If you have a model registered with a ModelViewSet and you registered the model's permissions using the register_permissions hook, you can now safely remove the hook.

If the viewset has {attr}~wagtail.admin.viewsets.model.ModelViewSet.inspect_view_enabled set to True, all permissions for the model are registered. Otherwise, the "view" permission is excluded from the registration.

To customize which permissions get registered for the model, you can override the {meth}~wagtail.admin.viewsets.model.ModelViewSet.get_permissions_to_register method.

This behavior now applies to snippets as well. Previously, the "view" permission for snippets is always registered regardless of inspect_view_enabled. If you wish to register the "view" permission, you can enable the inspect view:

class FooViewSet(SnippetViewSet):
    ...
    inspect_view_enabled = True

Alternatively, if you wish to register the "view" permission without enabling the inspect view (i.e. the previous behavior), you can override get_permissions_to_register like the following:

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

class FooViewSet(SnippetViewSet):
    def get_permissions_to_register(self):
        content_type = ContentType.objects.get_for_model(self.model)
        return Permission.objects.filter(content_type=content_type)

Upgrade considerations - deprecation of old functionality

Upgrade considerations - changes affecting Wagtail customisations

Changes to report views with the new Universal Listings UI

The report views have been reimplemented to use the new Universal Listings UI, which introduces AJAX-based filtering and support for the wagtail.admin.ui.tables framework. As a result, a number of changes have been made to the ReportView and PageReportView classes, as well as their templates.

If you have custom report views as documented in , you will need to make the following changes.

Change title to page_title

The title attribute on the view class should be renamed to page_title:

 class UnpublishedChangesReportView(PageReportView):
-    title = "Pages with unpublished changes"
+    page_title = "Pages with unpublished changes"

Set up the results-only view

Set the index_url_name and index_results_url_name attributes on the view class:

 class UnpublishedChangesReportView(PageReportView):
+    index_url_name = "unpublished_changes_report"
+    index_results_url_name = "unpublished_changes_report_results"

and register the results-only view:

 @hooks.register("register_admin_urls")
 def register_unpublished_changes_report_url():
     return [
         path("reports/unpublished-changes/", UnpublishedChangesReportView.as_view(), name="unpublished_changes_report"),
+        # Add a results-only view to add support for AJAX-based filtering
+        path("reports/unpublished-changes/results/", UnpublishedChangesReportView.as_view(results_only=True), name="unpublished_changes_report_results"),
     ]

Adjust the templates

If you are only extending the templates to add your own markup for the listing table (and not other parts of the view template), you need to change the template_name into results_template_name on the view class.

For a page report, the following changes are needed:

  • Change template_name to results_template_name, and optionally rename the template (e.g. reports/unpublished_changes_report.html to reports/unpublished_changes_report_results.html).
  • The template should extend from wagtailadmin/reports/base_page_report_results.html.
  • The listing and no_results blocks should be renamed to results and no_results_message, respectively.
 class UnpublishedChangesReportView(PageReportView):
-    template_name = "reports/unpublished_changes_report.html"
+    results_template_name = "reports/unpublished_changes_report_results.html"
 {# <project>/templates/reports/unpublished_changes_report_results.html #}

-{% extends "wagtailadmin/reports/base_page_report.html" %}
+{% extends "wagtailadmin/reports/base_page_report_results.html" %}

-{% block listing %}
+{% block results %}
     {% include "reports/include/_list_unpublished_changes.html" %}
 {% endblock %}
-{% block no_results %}
+{% block no_results_message %}
     <p>No pages with unpublished changes.</p>
 {% endblock %}

For a non-page report, the following changes are needed:

  • Change template_name to results_template_name, and optionally rename the template (e.g. reports/custom_non_page_report.html to reports/custom_non_page_report_results.html).
  • The template should extend from wagtailadmin/reports/base_report_results.html.
  • Existing templates will typically define a results block containing both the results listing and the "no results" message; these should now become separate blocks named results and no_results_message.

Before:

class CustomNonPageReportView(ReportView):
    template_name = "reports/custom_non_page_report.html"
{# <project>/templates/reports/custom_non_page_report.html #}
{% extends "wagtailadmin/reports/base_report.html" %}

{% block results %}
    {% if object_list %}
        <table class="listing">
            <!-- Table markup goes here -->
        </table>
    {% else %}
        <p>No results found.</p>
    {% endif %}
{% endblock %}

After:

class CustomNonPageReportView(ReportView):
    results_template_name = "reports/custom_non_page_report_results.html"
{# <project>/templates/reports/custom_non_page_report_results.html #}
{% extends "wagtailadmin/reports/base_report_results.html" %}

{% block results %}
    <table class="listing">
        <!-- Table markup goes here -->
    </table>
{% endblock %}

{% block no_results_message %}
    <p>No results found.</p>
{% endblock %}

If you need to completely customize the view's template, you can still override the template_name attribute on the view class. Note that both ReportView and PageReportView now use the wagtailadmin/reports/base_report.html template, which now extends the wagtailadmin/generic/listing.html template. The wagtailadmin/reports/base_page_report.html template is now unused and should be replaced with wagtailadmin/reports/base_report.html.

If you override template_name, it is still necessary to set results_template_name to a template that extends wagtailadmin/reports/base_report_results.html (or wagtailadmin/reports/base_page_report_results.html for page reports), so the view can correctly update the listing and show the active filters as you apply or remove any filters.

Upgrade considerations - changes to undocumented internals