Wagtail 8.0 release notes¶
August 25, 2026
What’s new¶
Wagtail REST API v3 (preview)¶
Wagtail 8.0 introduces a preview of a new v3 API, built on Django Ninja and type hints. The v2 API was designed for headless site and other data publication needs. v3 serves similar use cases, and adds support for CMS operations on top: authenticated clients can create, edit, publish and unpublish, move, copy, and revert content, and manage revisions, across pages, sites, locales, redirects, images, documents, and API-enabled snippets. You can create new pages with writable StreamField content, rich text as HTML or Markdown. The API auto-generates precise OpenAPI 3.1 schemas based on your project’s models, and uses API token authentication tied to user accounts. See the v3 API documentation for full details.
The v3 API is released as a preview to signify we want to adapt it based on feedback: it may change in backwards-incompatible ways in any release until stabilised. We welcome feedback via discussions, feature requests and bug reports. This feature was developed by Thibaud Colas and Sage Abdullah.
Custom base page models¶
This release introduces the ability to swap out the base Page model with a custom project-specific model. Any fields and methods defined on this model will be shared by all page types. This feature is only supported for newly-created projects, and certain add-on packages may not yet be compatible with it (see Adapting reusable apps to support custom base page models). This feature was developed by Matt Westcott.
Permission policy registry¶
A permission policy for every model managed by Wagtail is now registered to a global permission policy registry. The registry allows you to retrieve the permission policy of a model from anywhere in the code, which can be useful for performing permission checks outside of a view’s request-response cycle, such as in a background task. It can also be used to implement custom permission logic, including for Wagtail’s built-in models.
For more details, refer to the Permissions reference documentation. This feature was developed by Sage Abdullah.
Django 6.1 support¶
This release introduces formal support for Django 6.1.
Guide website improvements¶
The Wagtail user guide has been updated to use a new versioning scheme, better search and navigation, and better support for Right-to-Left (RTL) languages.
Thank you to Raghad Dahi for leading this work. For more information, read her project report: Streamlining content ops with LLMs: Wagtail user guide.
Automated dependency management¶
We now provide SBOM exports of our dependency graph in SPDX JSON format. This complements a number of improvements to dependency management, implemented by Sage Abdullah, Dan Braghis, and Thibaud Colas:
Automated testing with latest versions of all dependencies
Lockfiles and pinned dependencies for reproducible CI builds
zizmor for GitHub Actions quality checks
Automated dependency updates via Renovate
Security fix: Improper restriction handling on Pages admin API¶
The internal Pages admin API incorrectly returned page fields without access control when they were declared in api_fields. A user with access to the Wagtail admin could use this API to fetch draft and live page fields’ contents that are part of api_fields on the base page model (title, slug, seo_title, search_description), as well as all custom fields declared in api_fields.
Many thanks to xuliang@QAX for reporting this issue. For further details, please see security advisory GHSA-3vrh-m9w7-v94f.
Security fix: Identification of documents by SHA1 hash¶
By passing specific HTTP headers to the document serve URL endpoint, an attacker was able to determine whether a document with a given ID matched a specified SHA1 hash, regardless of any permission restrictions on the document or knowing its filename. This could allow an attacker to determine whether a document with a specific known hash is present in the Wagtail document library.
Many thanks to Anand Himanshu for reporting this issue. For further details, please see security advisory GHSA-92hv-j533-69wc.
Security fix: Improper restriction handling on descendant collections in Documents and Images API¶
The Documents and Images API incorrectly listed items in descendants of private collections, which should inherit the view restrictions defined on their ancestors. A user with access to the API could see the filename and name of documents and images in these descendant collections.
Many thanks to Ta Duc Thien for reporting this issue. For further details, please see security advisory GHSA-c2xx-cjmh-9q8f.
Security fix: Improper permission handling when copying snippets¶
A CMS user with “add” permission over a snippet model, but not “change” or “view” permission, could copy an existing snippet that they do not have access to, allowing them to view its contents.
Many thanks to tinyb0y for reporting this issue. For further details, please see security advisory GHSA-x5cx-w6p2-mxf2.
Security fix: Improper restriction handling on Page translation API endpoint¶
A CMS user with the “submit translations” permission, could use the Admin API’s “copy for translation” endpoint to copy an existing page that they do not have edit access to, allowing them to view its contents.
Many thanks to tinyb0y for reporting this issue. For further details, please see security advisory GHSA-jm5p-837g-rv8g.
Other features¶
Add customizability for all remaining page views to
PageViewSet(Sage Abdullah)Set
FieldPanel(required_on_save=True)forAbstractFormField’sfield_typefield (Alex Tomkins)Handle pasting of multiple tags separated by newlines or commas (Matthias Brück)
Make
Buttoncomponent render a<button>element when no URL is supplied (Nayeli De Jesus, LB (Ben Johnston), Sage Abdullah)Show site name in site switcher dropdown in site settings editor (Jack Morgan)
Improve clarity of different task states in workflow details dialog (Dan Braghis)
Add
submenu_hookattribute toViewSetGroupfor collecting submenu items registered via a hook (Hunzlah Malik, MariyaOT, Sage Abdullah)Respect
ViewSet.menu_orderwhen used in aViewSetGroup(Sage Abdullah)Use a more accessible label for blank values of
ChoiceBlock(Sage Abdullah)Use a more accessible label for blank values of dropdowns in locked page report filters (Sage Abdullah)
Make audit log messages for scheduling/unscheduling generic (Sage Abdullah)
Stop converting AVIF and WebP images to PNG by default (Thibaud Colas)
Add rich text serializing to HTML support in the v2 API (Thibaud Colas)
Expose the block
idas a template context variable when rendering children ofStreamBlockandListBlock(Sage Abdullah)Add extension blocks for image and document stats in the edit view templates (Preeti Singh)
Bug fixes¶
Make
SnippetChooserViewSet.widget_classa class instead of an instance (Amrinder Singh, Sage Abdullah)Prevent an error when approving a workflow that has been cancelled in a different session (Kailesh)
Accommodate multilingual sites in skipping the “choose parent” step when creating a new page from a flat page listing (Amrinder Singh)
Prevent error when moving a page to a destination with missing translations and
WAGTAILSIMPLETRANSLATION_SYNC_PAGE_TREE = True(Sahil Kumar)Handle Pillow detecting decompression bombs when validating image pixel count (Jake Howard, Sage Abdullah)
Use canonical URL for TED oEmbed provider (Marquis Nobles)
Prevent stale content types from breaking audit log message formatting (Thibaud Colas)
Prevent icons from capturing clicks inside buttons (Maciek Baron)
Ensure form field clean_name is consistently set on form pages if autosave runs prematurely (Joey Jurjens)
Enforce ‘choose’ permission on image chooser select-format view (Matt Westcott)
Documentation¶
Add reference documentation entry for
SnippetChooserViewSet(Sage Abdullah)Fix panel classname and deprecated usage of
format_htmlinconstruct_homepage_panelsexample (Andreas Nüßlein)Update django-ninja code examples to use new Meta class implemented in django-ninja V1 (Jack Whitworth)
Document
request.in_preview_panelto explain its use (Raghad Dahi)Update image format docs to encourage more intentional conversions (Thibaud Colas)
Clarify Wagtail XSS protections for uploaded documents (Thibaud Colas)
Add section on customizing StreamField block API output with
get_api_representation(Pranith Beeram)Removed now-deprecated
USE_L10Nsetting from internationalization and project setup documentation (Piyush Bhakuni)Add a new images overview page (Dmitry Khlopyev)
Maintenance¶
Rename
requestargument tocache_objectinPage._get_site_root_paths()for correctness (Kailesh)Fix blank choice tests for Django 6.1 (Sage Abdullah)
Ignore
EMAIL_BACKENDsetting deprecation on Django 6.1 when running project template tests (Sage Abdullah)Add
oneandnotmatch support toRulesController(LB (Ben Johnston))Refactor pages’ function-based views to class-based views (Sage Abdullah)
Enable flake8-bandit security-focused linting rules (Storm Heg)
Add support for latest Azure SDK for frontend cache invalidation (Sage Abdullah, Tomasz Knapik)
Update guide.wagtail.org links to new versioning scheme (Raghad Dahi)
Format Python code in documentation using ruff (Thibaud Colas)
Use Ubuntu 26.04 ARM runner for GitHub Actions workflows (Storm Heg)
Upgrade considerations - removal of deprecated features from Wagtail 6.4 - 7.3¶
Features previously deprecated in Wagtail 6.4, 7.0, 7.1, 7.2, and 7.3 have been fully removed:
The
construct_wagtail_userbarhook now receives a third argumentpagein addition torequestanditems; hook functions that only accept two arguments will now fail.The JavaScript functions
buildExpandingFormsetandinitPrefillTitleFromFilenameare removed.The settings
TAG_LIMITandTAG_SPACES_ALLOWEDare replaced byWAGTAIL_TAG_LIMITandWAGTAIL_TAG_SPACES_ALLOWED.Custom listing views using the template
wagtailadmin/generic/index.htmlmust now provide abreadcrumbs_itemscontext variable.The template
wagtailadmin/pages/_editor_js.htmlis removed.The
PageListingButton,SnippetListingButtonandUserListingButtonclasses are removed in favour ofListingButtonandButton.The function
wagtail.admin.signals.init_new_pageis moved towagtail.signals.init_new_page.The module
wagtail.telepathis moved towagtail.admin.telepath.The module
wagtail.widget_adaptersis moved towagtail.admin.telepath.widgets.The JavaScript include
wagtailadmin/js/telepath/telepath.jsis removed.The
INDEXoption onWAGTAILSEARCH_BACKENDSis replaced byINDEX_PREFIX(for example,"INDEX": "mysite"now becomes"INDEX_PREFIX": "mysite_").Userbar items now follow the template component API and do not provide a
rendermethod.The
resetValueproperty is removed fromTeleportController.
For additional details on these changes, see:
Upgrade considerations - changes affecting all projects¶
AVIF and WebP images are no longer converted to PNG by default¶
Browser support for AVIF and WebP is now solid enough that Wagtail no longer converts images in these formats to PNG when no output format is specified. Rather than relying on this setting, we recommend controlling output formats explicitly with the format-* filter or picture template tag. See Customizing output formats for more details.
If you need to retain the previous behavior as-is, add the following to your settings:
WAGTAILIMAGES_FORMAT_CONVERSIONS = {
"bmp": "png",
"heic": "jpeg",
"avif": "png",
"webp": "png",
}
Upgrade considerations - deprecation of old functionality¶
Support for legacy versions of azure-mgmt-cdn, azure-mgmt-frontdoor, and azure-mgmt-resource packages will be dropped¶
If you are using the front-end cache invalidator module (wagtail.contrib.frontend_cache) with Azure CDN or Azure Front Door, the following packages need to be updated:
For Azure CDN: upgrade
azure-mgmt-cdnto version 13 or aboveFor Azure Front Door: upgrade
azure-mgmt-frontdoorto version 1.1 or above
In addition, if you do not set SUBCRIPTION_ID and thus rely on azure-mgmt-resource to retrieve the default subscription, you should install the azure-mgmt-subscription package instead of (or in addition to) azure-mgmt-resource.
Support for older versions will be dropped in a future release.
Upgrade considerations - changes affecting Wagtail customizations¶
Support for custom base page models in add-on packages¶
Reusable apps that work with the Page model are likely to require updating in order to be usable on projects that use the new custom base page model feature. This process is detailed at Adapting reusable apps to support custom base page models.
Custom permission policy in viewsets must be registered separately¶
If you use the Generic views and have a ModelViewSet, SnippetViewSet, or ChooserViewSet that defines a custom value for the (previously-undocumented) permission_policy, you must now register the permission policy separately.
Registering a permission policy can be done by calling
register_permission_policy(Model, <policy_instance>)
at the top of the model app’s wagtail_hooks.py.
# wagtail_hooks.py
from wagtail.permissions import register_permission_policy
from .models import MyModel
register_permission_policy(MyModel, my_custom_policy_instance)
... # More customizations
Alternatively, you can also put the registration in the app’s
AppConfig.ready().
# apps.py
class MyAppConfig(AppConfig):
...
def ready(self):
from wagtail.permissions import register_permission_policy
from .models import MyModel
register_permission_policy(MyModel, my_custom_policy_instance)
If you do not register the permission policy explicitly, Wagtail will automatically register the viewset’s permission_policy, and a deprecation warning will be raised. This support will be removed in a future release.
This change does not affect viewsets that do not have a custom permission_policy.
SnippetChooserViewSet.widget_class is now a class¶
The SnippetChooserViewSet.widget_class attribute now correctly returns a widget class instead of an instance, consistent with ChooserViewSet.widget_class. This change may require updates to any customizations that relied on the previous behavior, such as an override in a SnippetChooserViewSet subclass that uses super().widget_class.
Setting submissions_list_view_class on form page models no longer works¶
The submissions_list_view_class attribute on the form builder’s AbstractForm model, previously documented at Customize form submissions listing in Wagtail Admin, is no longer directly usable. This is because the wagtail.contrib.forms.views module can no longer be imported at model load time without introducing a circular import, and so there is no way to refer to a subclass of SubmissionsListView within a model definition. Instead, the get_submissions_list_view_class method can be overridden to achieve the same result. First, the definition of the SubmissionsListView subclass, and the import of SubmissionsListView, should be moved to a separate views module within the app. Then, the attribute assignment:
class FormPage(AbstractEmailForm):
# ...
submissions_list_view_class = CustomSubmissionsListView
can be replaced with:
class FormPage(AbstractEmailForm):
# ...
def get_submissions_list_view_class(self):
from myapp.views import CustomSubmissionsListView
return CustomSubmissionsListView
Upgrade considerations - changes to undocumented internals¶
request argument to Page._get_site_root_paths is now cache_object¶
The request argument to the undocumented method Page._get_site_root_paths() is renamed to cache_object to reflect the fact that it is not always a request object, but may be any object that can be used for caching purposes.
If you pass request as a positional argument, no changes are needed. If you pass request as a keyword argument to this method, you will need to update the argument name to cache_object in your code or turn it into a positional argument.
Passing a request keyword argument will continue to work for now and raise a deprecation warning, but support for this will be removed in a future release.