wagtail 7.2.1__py3-none-any.whl → 7.3rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wagtail/__init__.py +1 -1
- wagtail/actions/copy_for_translation.py +4 -2
- wagtail/admin/action_menu.py +4 -1
- wagtail/admin/api/actions/convert_alias.py +2 -2
- wagtail/admin/api/actions/copy.py +2 -2
- wagtail/admin/api/actions/copy_for_translation.py +2 -2
- wagtail/admin/api/actions/create_alias.py +2 -2
- wagtail/admin/api/actions/delete.py +1 -1
- wagtail/admin/api/actions/move.py +1 -1
- wagtail/admin/api/actions/publish.py +2 -2
- wagtail/admin/api/actions/revert_to_page_revision.py +2 -2
- wagtail/admin/api/actions/unpublish.py +1 -1
- wagtail/admin/api/filters.py +2 -2
- wagtail/admin/compare.py +22 -0
- wagtail/admin/forms/account.py +52 -1
- wagtail/admin/forms/comments.py +53 -0
- wagtail/admin/forms/models.py +36 -0
- wagtail/admin/forms/pages.py +7 -0
- wagtail/admin/forms/workflows.py +5 -2
- wagtail/admin/icons.py +4 -3
- wagtail/admin/locale/ar/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ar/LC_MESSAGES/django.po +35 -0
- wagtail/admin/locale/en/LC_MESSAGES/django.po +262 -234
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +72 -43
- wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/django.po +566 -6
- wagtail/admin/locale/it/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/djangojs.po +40 -2
- wagtail/admin/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/nl/LC_MESSAGES/django.po +2 -2
- wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/django.po +330 -15
- wagtail/admin/locale/sv/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/djangojs.po +3 -2
- wagtail/admin/panels/comment_panel.py +1 -51
- wagtail/admin/panels/title_field_panel.py +3 -1
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/templates/wagtailadmin/base.html +1 -1
- wagtail/admin/templates/wagtailadmin/generic/edit_partials.html +100 -0
- wagtail/admin/templates/wagtailadmin/generic/form.html +26 -5
- wagtail/admin/templates/wagtailadmin/generic/includes/_loaded_revision_inputs.html +3 -0
- wagtail/admin/templates/wagtailadmin/generic/listing_results.html +1 -17
- wagtail/admin/templates/wagtailadmin/pages/create.html +14 -4
- wagtail/admin/templates/wagtailadmin/pages/edit.html +16 -3
- wagtail/admin/templates/wagtailadmin/pages/edit_partials.html +31 -0
- wagtail/admin/templates/wagtailadmin/pages/index_results.html +1 -9
- wagtail/admin/templates/wagtailadmin/shared/autosave/indicator.html +36 -0
- wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/editing_sessions/list.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/editing_sessions/module.html +19 -3
- wagtail/admin/templates/wagtailadmin/shared/headers/_actions.html +5 -0
- wagtail/admin/templates/wagtailadmin/shared/headers/_history_icon_link.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +8 -9
- wagtail/admin/templates/wagtailadmin/shared/listing/filter_partials.html +19 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +3 -3
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/side_panel.html +3 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/privacy.html +18 -6
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +11 -4
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/workflow.html +22 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +1 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panels.html +1 -2
- wagtail/admin/templates/wagtailadmin/shared/unsaved_changes_warning.html +20 -20
- wagtail/admin/templates/wagtailadmin/userbar/base.html +2 -0
- wagtail/admin/templates/wagtailadmin/userbar/item_accessibility.html +1 -1
- wagtail/admin/templatetags/wagtailadmin_tags.py +6 -14
- wagtail/admin/tests/pages/test_create_page.py +298 -1
- wagtail/admin/tests/pages/test_custom_listing.py +48 -2
- wagtail/admin/tests/pages/test_edit_page.py +721 -7
- wagtail/admin/tests/pages/test_explorer_view.py +9 -5
- wagtail/admin/tests/pages/test_page_search.py +15 -0
- wagtail/admin/tests/pages/test_revisions.py +4 -0
- wagtail/admin/tests/test_account_management.py +88 -2
- wagtail/admin/tests/test_collections_views.py +15 -15
- wagtail/admin/tests/test_compare.py +34 -0
- wagtail/admin/tests/test_editing_sessions.py +230 -8
- wagtail/admin/tests/test_forms.py +192 -1
- wagtail/admin/tests/test_icon_sprite.py +22 -2
- wagtail/admin/tests/test_page_chooser.py +13 -13
- wagtail/admin/tests/test_reports_views.py +4 -1
- wagtail/admin/tests/test_userbar.py +69 -5
- wagtail/admin/tests/test_views_generic.py +5 -5
- wagtail/admin/tests/test_workflows.py +14 -12
- wagtail/admin/tests/viewsets/test_model_viewset.py +13 -0
- wagtail/admin/ui/autosave.py +5 -0
- wagtail/admin/ui/editing_sessions.py +3 -0
- wagtail/admin/ui/side_panels.py +19 -20
- wagtail/admin/userbar.py +48 -27
- wagtail/admin/views/bulk_action/dispatcher.py +2 -2
- wagtail/admin/views/chooser.py +6 -6
- wagtail/admin/views/editing_sessions.py +20 -7
- wagtail/admin/views/generic/__init__.py +1 -0
- wagtail/admin/views/generic/chooser.py +5 -5
- wagtail/admin/views/generic/mixins.py +143 -26
- wagtail/admin/views/generic/models.py +157 -27
- wagtail/admin/views/generic/ordering.py +1 -1
- wagtail/admin/views/generic/preview.py +4 -4
- wagtail/admin/views/home.py +3 -1
- wagtail/admin/views/pages/create.py +77 -29
- wagtail/admin/views/pages/edit.py +160 -34
- wagtail/admin/views/pages/preview.py +4 -4
- wagtail/admin/views/pages/revisions.py +3 -0
- wagtail/admin/views/pages/search.py +4 -4
- wagtail/admin/views/pages/usage.py +2 -2
- wagtail/admin/views/tags.py +2 -2
- wagtail/admin/views/workflows.py +73 -54
- wagtail/admin/viewsets/model.py +34 -8
- wagtail/admin/widgets/button.py +11 -4
- wagtail/admin/widgets/chooser.py +6 -4
- wagtail/admin/widgets/slug.py +1 -1
- wagtail/api/v2/filters.py +27 -21
- wagtail/api/v2/pagination.py +4 -4
- wagtail/api/v2/views.py +7 -7
- wagtail/blocks/list_block.py +0 -8
- wagtail/blocks/migrations/migrate_operation.py +8 -1
- wagtail/blocks/stream_block.py +2 -10
- wagtail/blocks/struct_block.py +192 -12
- wagtail/compat.py +2 -2
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/forms/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/it/LC_MESSAGES/django.po +40 -2
- wagtail/contrib/frontend_cache/backends/azure.py +6 -6
- wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
- wagtail/contrib/frontend_cache/utils.py +1 -1
- wagtail/contrib/redirects/forms.py +1 -1
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +14 -14
- wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.po +15 -2
- wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.po +16 -3
- wagtail/contrib/redirects/middleware.py +11 -7
- wagtail/contrib/redirects/models.py +17 -1
- wagtail/contrib/redirects/tests/test_import_admin_views.py +3 -3
- wagtail/contrib/redirects/tests/test_redirects.py +56 -8
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +43 -2
- wagtail/contrib/search_promotions/tests.py +1 -1
- wagtail/contrib/search_promotions/views/settings.py +24 -25
- wagtail/contrib/settings/jinja2tags.py +2 -2
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/settings/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/it/LC_MESSAGES/django.po +6 -2
- wagtail/contrib/settings/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/sv/LC_MESSAGES/django.po +3 -2
- wagtail/contrib/settings/tests/generic/test_admin.py +118 -2
- wagtail/contrib/settings/tests/site_specific/test_admin.py +78 -15
- wagtail/contrib/settings/tests/site_specific/test_model.py +2 -2
- wagtail/contrib/settings/views.py +7 -0
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/simple_translation/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/it/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/styleguide/tests.py +2 -0
- wagtail/contrib/styleguide/views.py +4 -5
- wagtail/contrib/table_block/locale/ar/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/ar/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/typed_table_block/blocks.py +37 -0
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/contrib/typed_table_block/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/sv/LC_MESSAGES/django.po +4 -3
- wagtail/contrib/typed_table_block/tests.py +108 -0
- wagtail/coreutils.py +4 -4
- wagtail/documents/__init__.py +4 -4
- wagtail/documents/locale/en/LC_MESSAGES/django.po +15 -15
- wagtail/documents/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/it/LC_MESSAGES/django.po +32 -2
- wagtail/documents/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/sv/LC_MESSAGES/django.po +32 -4
- wagtail/documents/models.py +1 -1
- wagtail/documents/tests/test_admin_views.py +19 -4
- wagtail/documents/tests/test_search.py +0 -2
- wagtail/documents/tests/test_views.py +6 -4
- wagtail/documents/views/bulk_actions/add_tags.py +1 -1
- wagtail/embeds/finders/facebook.py +3 -3
- wagtail/embeds/finders/instagram.py +3 -3
- wagtail/embeds/finders/oembed.py +7 -2
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/oembed_providers.py +8 -0
- wagtail/embeds/tests/test_embeds.py +35 -0
- wagtail/images/__init__.py +4 -4
- wagtail/images/admin_urls.py +3 -3
- wagtail/images/blocks.py +1 -1
- wagtail/images/formats.py +2 -2
- wagtail/images/image_operations.py +2 -2
- wagtail/images/locale/en/LC_MESSAGES/django.po +44 -40
- wagtail/images/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/it/LC_MESSAGES/django.po +50 -4
- wagtail/images/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/nl/LC_MESSAGES/django.po +3 -3
- wagtail/images/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/sv/LC_MESSAGES/django.po +49 -6
- wagtail/images/models.py +11 -10
- wagtail/images/templates/wagtailimages/images/index_results.html +1 -1
- wagtail/images/templates/wagtailimages/images/url_generator.html +17 -38
- wagtail/images/templates/wagtailimages/images/url_generator_output.html +28 -0
- wagtail/images/templatetags/wagtailimages_tags.py +4 -4
- wagtail/images/tests/test_admin_views.py +432 -59
- wagtail/images/tests/test_image_operations.py +2 -2
- wagtail/images/tests/test_models.py +0 -2
- wagtail/images/views/bulk_actions/add_tags.py +1 -1
- wagtail/images/views/images.py +72 -39
- wagtail/locale/en/LC_MESSAGES/django.po +103 -105
- wagtail/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/it/LC_MESSAGES/django.po +105 -2
- wagtail/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sv/LC_MESSAGES/django.po +95 -12
- wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/it/LC_MESSAGES/django.po +13 -2
- wagtail/locales/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/sv/LC_MESSAGES/django.po +4 -3
- wagtail/locales/tests.py +5 -5
- wagtail/models/i18n.py +4 -6
- wagtail/models/media.py +18 -0
- wagtail/models/pages.py +65 -11
- wagtail/models/reference_index.py +15 -0
- wagtail/models/revisions.py +40 -12
- wagtail/models/workflows.py +0 -3
- wagtail/permission_policies/base.py +2 -2
- wagtail/permission_policies/collections.py +2 -2
- wagtail/project_template/requirements.txt +2 -2
- wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/signal_handlers.py +1 -0
- wagtail/sites/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/sites/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/sites/locale/sv/LC_MESSAGES/django.po +3 -2
- wagtail/sites/tests.py +7 -7
- wagtail/snippets/action_menu.py +2 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +23 -13
- wagtail/snippets/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/sv/LC_MESSAGES/django.po +12 -1
- wagtail/snippets/tests/test_chooser_block.py +197 -0
- wagtail/snippets/tests/test_chooser_panel.py +149 -0
- wagtail/snippets/tests/test_chooser_views.py +375 -0
- wagtail/snippets/tests/test_chooser_widget.py +22 -0
- wagtail/snippets/tests/test_compare_revisions_view.py +167 -0
- wagtail/snippets/tests/test_copy_view.py +38 -0
- wagtail/snippets/tests/test_create_view.py +1159 -0
- wagtail/snippets/tests/test_delete_view.py +225 -0
- wagtail/snippets/tests/test_edit_view.py +2882 -0
- wagtail/snippets/tests/test_history_view.py +182 -0
- wagtail/snippets/tests/test_index_view.py +105 -0
- wagtail/snippets/tests/test_list_view.py +786 -0
- wagtail/snippets/tests/test_locking.py +28 -0
- wagtail/snippets/tests/test_permissions.py +167 -0
- wagtail/snippets/tests/test_preview.py +3 -3
- wagtail/snippets/tests/test_revert_view.py +343 -0
- wagtail/snippets/tests/test_snippet_models.py +112 -0
- wagtail/snippets/tests/test_unpublish_view.py +228 -0
- wagtail/snippets/tests/test_unschedule_view.py +151 -0
- wagtail/snippets/tests/test_viewset.py +38 -5
- wagtail/snippets/views/snippets.py +78 -30
- wagtail/snippets/widgets.py +2 -2
- wagtail/templatetags/wagtailcore_tags.py +2 -2
- wagtail/test/dummy_external_storage.py +1 -1
- wagtail/test/testapp/fixtures/test.json +22 -0
- wagtail/test/testapp/fixtures/test_empty.json +2 -0
- wagtail/test/testapp/fixtures/test_explorable_pages.json +10 -0
- wagtail/test/testapp/fixtures/test_specific.json +9 -0
- wagtail/test/testapp/migrations/0059_nopromotepage.py +25 -0
- wagtail/test/testapp/models.py +7 -0
- wagtail/test/testapp/views.py +5 -0
- wagtail/test/utils/page_tests.py +7 -7
- wagtail/test/utils/wagtail_factories/builder.py +2 -2
- wagtail/tests/streamfield_migrations/test_migrations.py +35 -0
- wagtail/tests/test_blocks.py +321 -61
- wagtail/tests/test_collection_model.py +12 -0
- wagtail/tests/test_page_model.py +190 -1
- wagtail/tests/test_page_privacy.py +5 -0
- wagtail/tests/test_reference_index.py +42 -0
- wagtail/tests/test_revision_model.py +118 -1
- wagtail/tests/test_utils.py +2 -2
- wagtail/users/locale/en/LC_MESSAGES/django.po +14 -14
- wagtail/users/locale/id_ID/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/id_ID/LC_MESSAGES/django.po +6 -2
- wagtail/users/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/it/LC_MESSAGES/django.po +14 -2
- wagtail/users/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sv/LC_MESSAGES/django.po +48 -17
- wagtail/users/tests/test_admin_views.py +39 -25
- wagtail/users/utils.py +4 -1
- wagtail/users/views/groups.py +19 -5
- wagtail/users/wagtail_hooks.py +1 -1
- wagtail/utils/loading.py +2 -2
- wagtail-7.3rc1.data/data/AGENTS.md +21 -0
- wagtail-7.3rc1.data/data/CHANGELOG.txt +4941 -0
- wagtail-7.3rc1.data/data/CODE_OF_CONDUCT.md +71 -0
- wagtail-7.3rc1.data/data/CONTRIBUTORS.md +999 -0
- wagtail-7.3rc1.data/data/SPONSORS.md +55 -0
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/METADATA +6 -6
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/RECORD +310 -280
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/WHEEL +1 -1
- wagtail/images/static/wagtailimages/js/image-url-generator.js +0 -1
- wagtail/snippets/tests/test_snippets.py +0 -6377
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/licenses/LICENSE +0 -0
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/top_level.txt +0 -0
wagtail/admin/widgets/button.py
CHANGED
|
@@ -19,7 +19,13 @@ class BaseButton(Component):
|
|
|
19
19
|
allow_in_dropdown = False
|
|
20
20
|
|
|
21
21
|
def __init__(
|
|
22
|
-
self,
|
|
22
|
+
self,
|
|
23
|
+
label="",
|
|
24
|
+
url=None,
|
|
25
|
+
classname="",
|
|
26
|
+
icon_name=None,
|
|
27
|
+
attrs=None,
|
|
28
|
+
priority=1000,
|
|
23
29
|
):
|
|
24
30
|
if label:
|
|
25
31
|
self.label = label
|
|
@@ -33,7 +39,8 @@ class BaseButton(Component):
|
|
|
33
39
|
self.icon_name = icon_name
|
|
34
40
|
|
|
35
41
|
self.attrs = self.attrs.copy()
|
|
36
|
-
|
|
42
|
+
if attrs:
|
|
43
|
+
self.attrs.update(attrs)
|
|
37
44
|
self.priority = priority
|
|
38
45
|
|
|
39
46
|
def get_context_data(self, parent_context):
|
|
@@ -115,12 +122,12 @@ class HeaderButton(BaseButton):
|
|
|
115
122
|
url=None,
|
|
116
123
|
classname="",
|
|
117
124
|
icon_name=None,
|
|
118
|
-
attrs=
|
|
125
|
+
attrs=None,
|
|
119
126
|
icon_only=False,
|
|
120
127
|
**kwargs,
|
|
121
128
|
):
|
|
122
129
|
classname = f"{classname} w-header-button button".strip()
|
|
123
|
-
attrs = attrs.copy()
|
|
130
|
+
attrs = attrs.copy() if attrs else {}
|
|
124
131
|
if icon_only:
|
|
125
132
|
controller = f"{attrs.get('data-controller', '')} w-tooltip".strip()
|
|
126
133
|
attrs["data-controller"] = controller
|
wagtail/admin/widgets/chooser.py
CHANGED
|
@@ -157,8 +157,10 @@ class BaseChooser(widgets.Input):
|
|
|
157
157
|
# so let's make sure it fails early in the process
|
|
158
158
|
try:
|
|
159
159
|
id_ = attrs["id"]
|
|
160
|
-
except (KeyError, TypeError):
|
|
161
|
-
raise TypeError(
|
|
160
|
+
except (KeyError, TypeError) as e:
|
|
161
|
+
raise TypeError(
|
|
162
|
+
"BaseChooser cannot be rendered without an 'id' attribute"
|
|
163
|
+
) from e
|
|
162
164
|
|
|
163
165
|
value_data = self.get_value_data(value)
|
|
164
166
|
widget_html = self.render_html(name, value_data, attrs)
|
|
@@ -241,12 +243,12 @@ class AdminPageChooser(BaseChooser):
|
|
|
241
243
|
for model in target_models:
|
|
242
244
|
try:
|
|
243
245
|
cleaned_target_models.append(resolve_model_string(model))
|
|
244
|
-
except (ValueError, LookupError):
|
|
246
|
+
except (ValueError, LookupError) as e:
|
|
245
247
|
raise ImproperlyConfigured(
|
|
246
248
|
"Could not resolve %r into a model. "
|
|
247
249
|
"Model names should be in the form app_label.model_name"
|
|
248
250
|
% (model,)
|
|
249
|
-
)
|
|
251
|
+
) from e
|
|
250
252
|
else:
|
|
251
253
|
cleaned_target_models = [Page]
|
|
252
254
|
|
wagtail/admin/widgets/slug.py
CHANGED
wagtail/api/v2/filters.py
CHANGED
|
@@ -45,7 +45,7 @@ class FieldsFilter(BaseFilterBackend):
|
|
|
45
45
|
raise BadRequestError(
|
|
46
46
|
"field filter error. '%s' is not a valid value for %s (%s)"
|
|
47
47
|
% (value, field_name, str(e))
|
|
48
|
-
)
|
|
48
|
+
) from e
|
|
49
49
|
|
|
50
50
|
if "\x00" in str(value):
|
|
51
51
|
raise BadRequestError(
|
|
@@ -106,8 +106,10 @@ class OrderingFilter(BaseFilterBackend):
|
|
|
106
106
|
|
|
107
107
|
try:
|
|
108
108
|
return queryset.order_by(*validated_fields)
|
|
109
|
-
except FieldError:
|
|
110
|
-
raise BadRequestError(
|
|
109
|
+
except FieldError as e:
|
|
110
|
+
raise BadRequestError(
|
|
111
|
+
f"cannot order by '{order_param}' (invalid field)"
|
|
112
|
+
) from e
|
|
111
113
|
|
|
112
114
|
|
|
113
115
|
class SearchFilter(BaseFilterBackend):
|
|
@@ -145,13 +147,13 @@ class SearchFilter(BaseFilterBackend):
|
|
|
145
147
|
"cannot filter by '{}' while searching (field is not indexed)".format(
|
|
146
148
|
e.field_name
|
|
147
149
|
)
|
|
148
|
-
)
|
|
150
|
+
) from e
|
|
149
151
|
except OrderByFieldError as e:
|
|
150
152
|
raise BadRequestError(
|
|
151
153
|
"cannot order by '{}' while searching (field is not indexed)".format(
|
|
152
154
|
e.field_name
|
|
153
155
|
)
|
|
154
|
-
)
|
|
156
|
+
) from e
|
|
155
157
|
|
|
156
158
|
return queryset
|
|
157
159
|
|
|
@@ -170,13 +172,13 @@ class ChildOfFilter(BaseFilterBackend):
|
|
|
170
172
|
raise ValueError()
|
|
171
173
|
|
|
172
174
|
parent_page = view.get_base_queryset().get(id=parent_page_id)
|
|
173
|
-
except ValueError:
|
|
175
|
+
except ValueError as e:
|
|
174
176
|
if request.GET["child_of"] == "root":
|
|
175
177
|
parent_page = view.get_root_page()
|
|
176
178
|
else:
|
|
177
|
-
raise BadRequestError("child_of must be a positive integer")
|
|
178
|
-
except Page.DoesNotExist:
|
|
179
|
-
raise BadRequestError("parent page doesn't exist")
|
|
179
|
+
raise BadRequestError("child_of must be a positive integer") from e
|
|
180
|
+
except Page.DoesNotExist as e:
|
|
181
|
+
raise BadRequestError("parent page doesn't exist") from e
|
|
180
182
|
|
|
181
183
|
queryset = queryset.child_of(parent_page)
|
|
182
184
|
|
|
@@ -202,10 +204,10 @@ class AncestorOfFilter(BaseFilterBackend):
|
|
|
202
204
|
raise ValueError()
|
|
203
205
|
|
|
204
206
|
descendant_page = view.get_base_queryset().get(id=descendant_page_id)
|
|
205
|
-
except ValueError:
|
|
206
|
-
raise BadRequestError("ancestor_of must be a positive integer")
|
|
207
|
-
except Page.DoesNotExist:
|
|
208
|
-
raise BadRequestError("descendant page doesn't exist")
|
|
207
|
+
except ValueError as e:
|
|
208
|
+
raise BadRequestError("ancestor_of must be a positive integer") from e
|
|
209
|
+
except Page.DoesNotExist as e:
|
|
210
|
+
raise BadRequestError("descendant page doesn't exist") from e
|
|
209
211
|
|
|
210
212
|
queryset = queryset.ancestor_of(descendant_page)
|
|
211
213
|
|
|
@@ -230,13 +232,15 @@ class DescendantOfFilter(BaseFilterBackend):
|
|
|
230
232
|
raise ValueError()
|
|
231
233
|
|
|
232
234
|
parent_page = view.get_base_queryset().get(id=parent_page_id)
|
|
233
|
-
except ValueError:
|
|
235
|
+
except ValueError as e:
|
|
234
236
|
if request.GET["descendant_of"] == "root":
|
|
235
237
|
parent_page = view.get_root_page()
|
|
236
238
|
else:
|
|
237
|
-
raise BadRequestError(
|
|
238
|
-
|
|
239
|
-
|
|
239
|
+
raise BadRequestError(
|
|
240
|
+
"descendant_of must be a positive integer"
|
|
241
|
+
) from e
|
|
242
|
+
except Page.DoesNotExist as e:
|
|
243
|
+
raise BadRequestError("ancestor page doesn't exist") from e
|
|
240
244
|
|
|
241
245
|
queryset = queryset.descendant_of(parent_page)
|
|
242
246
|
|
|
@@ -257,13 +261,15 @@ class TranslationOfFilter(BaseFilterBackend):
|
|
|
257
261
|
raise ValueError()
|
|
258
262
|
|
|
259
263
|
page = view.get_base_queryset().get(id=page_id)
|
|
260
|
-
except ValueError:
|
|
264
|
+
except ValueError as e:
|
|
261
265
|
if request.GET["translation_of"] == "root":
|
|
262
266
|
page = view.get_root_page()
|
|
263
267
|
else:
|
|
264
|
-
raise BadRequestError(
|
|
265
|
-
|
|
266
|
-
|
|
268
|
+
raise BadRequestError(
|
|
269
|
+
"translation_of must be a positive integer"
|
|
270
|
+
) from e
|
|
271
|
+
except Page.DoesNotExist as e:
|
|
272
|
+
raise BadRequestError("translation_of page doesn't exist") from e
|
|
267
273
|
|
|
268
274
|
_filtered_by_child_of = getattr(queryset, "_filtered_by_child_of", None)
|
|
269
275
|
|
wagtail/api/v2/pagination.py
CHANGED
|
@@ -15,16 +15,16 @@ class WagtailPagination(BasePagination):
|
|
|
15
15
|
offset = int(request.GET.get("offset", 0))
|
|
16
16
|
if offset < 0:
|
|
17
17
|
raise ValueError()
|
|
18
|
-
except ValueError:
|
|
19
|
-
raise BadRequestError("offset must be a positive integer")
|
|
18
|
+
except ValueError as e:
|
|
19
|
+
raise BadRequestError("offset must be a positive integer") from e
|
|
20
20
|
|
|
21
21
|
try:
|
|
22
22
|
limit_default = 20 if not limit_max else min(20, limit_max)
|
|
23
23
|
limit = int(request.GET.get("limit", limit_default))
|
|
24
24
|
if limit < 0:
|
|
25
25
|
raise ValueError()
|
|
26
|
-
except ValueError:
|
|
27
|
-
raise BadRequestError("limit must be a positive integer")
|
|
26
|
+
except ValueError as e:
|
|
27
|
+
raise BadRequestError("limit must be a positive integer") from e
|
|
28
28
|
|
|
29
29
|
if limit_max and limit > limit_max:
|
|
30
30
|
raise BadRequestError("limit cannot be higher than %d" % limit_max)
|
wagtail/api/v2/views.py
CHANGED
|
@@ -109,8 +109,8 @@ class BaseAPIViewSet(GenericViewSet):
|
|
|
109
109
|
if obj is None:
|
|
110
110
|
raise self.model.DoesNotExist
|
|
111
111
|
|
|
112
|
-
except self.model.DoesNotExist:
|
|
113
|
-
raise Http404("not found")
|
|
112
|
+
except self.model.DoesNotExist as e:
|
|
113
|
+
raise Http404("not found") from e
|
|
114
114
|
|
|
115
115
|
# Generate redirect
|
|
116
116
|
url = get_object_detail_url(
|
|
@@ -366,7 +366,7 @@ class BaseAPIViewSet(GenericViewSet):
|
|
|
366
366
|
try:
|
|
367
367
|
fields_config = parse_fields_parameter(request.GET["fields"])
|
|
368
368
|
except ValueError as e:
|
|
369
|
-
raise BadRequestError("fields error: %s" % str(e))
|
|
369
|
+
raise BadRequestError("fields error: %s" % str(e)) from e
|
|
370
370
|
else:
|
|
371
371
|
# Use default fields
|
|
372
372
|
fields_config = []
|
|
@@ -549,10 +549,10 @@ class PagesAPIViewSet(BaseAPIViewSet):
|
|
|
549
549
|
}
|
|
550
550
|
try:
|
|
551
551
|
site = Site.objects.get(**query)
|
|
552
|
-
except Site.MultipleObjectsReturned:
|
|
552
|
+
except Site.MultipleObjectsReturned as e:
|
|
553
553
|
raise BadRequestError(
|
|
554
554
|
"Your query returned multiple sites. Try adding a port number to your site filter."
|
|
555
|
-
)
|
|
555
|
+
) from e
|
|
556
556
|
else:
|
|
557
557
|
# Otherwise, find the site from the request
|
|
558
558
|
site = Site.find_for_request(self.request)
|
|
@@ -579,8 +579,8 @@ class PagesAPIViewSet(BaseAPIViewSet):
|
|
|
579
579
|
try:
|
|
580
580
|
models_type = request.GET.get("type", None)
|
|
581
581
|
models = models_type and page_models_from_string(models_type) or []
|
|
582
|
-
except (LookupError, ValueError):
|
|
583
|
-
raise BadRequestError("type doesn't exist")
|
|
582
|
+
except (LookupError, ValueError) as e:
|
|
583
|
+
raise BadRequestError("type doesn't exist") from e
|
|
584
584
|
|
|
585
585
|
if not models:
|
|
586
586
|
if self.model == Page:
|
wagtail/blocks/list_block.py
CHANGED
|
@@ -458,14 +458,6 @@ class ListBlockAdapter(Adapter):
|
|
|
458
458
|
"classname": block.meta.form_classname,
|
|
459
459
|
"attrs": block.meta.form_attrs or {},
|
|
460
460
|
"collapsed": block.meta.collapsed,
|
|
461
|
-
"strings": {
|
|
462
|
-
"MOVE_UP": _("Move up"),
|
|
463
|
-
"MOVE_DOWN": _("Move down"),
|
|
464
|
-
"DRAG": _("Drag"),
|
|
465
|
-
"DUPLICATE": _("Duplicate"),
|
|
466
|
-
"DELETE": _("Delete"),
|
|
467
|
-
"ADD": _("Add"),
|
|
468
|
-
},
|
|
469
461
|
}
|
|
470
462
|
help_text = getattr(block.meta, "help_text", None)
|
|
471
463
|
if help_text:
|
|
@@ -155,8 +155,15 @@ class MigrateStreamData(RunPython):
|
|
|
155
155
|
|
|
156
156
|
updated_revisions_buffer = []
|
|
157
157
|
for revision in revision_queryset.iterator(chunk_size=self.chunk_size):
|
|
158
|
+
try:
|
|
159
|
+
json_data = revision.content[self.field_name]
|
|
160
|
+
except KeyError:
|
|
161
|
+
# The requested field doesn't exist on this revision. The revision may
|
|
162
|
+
# have been created before the creation of the field. Don't process this
|
|
163
|
+
# revision.
|
|
164
|
+
continue
|
|
158
165
|
|
|
159
|
-
raw_data = json.loads(
|
|
166
|
+
raw_data = json.loads(json_data)
|
|
160
167
|
for operation, block_path_str in self.operations_and_block_paths:
|
|
161
168
|
try:
|
|
162
169
|
raw_data = utils.apply_changes_to_raw_data(
|
wagtail/blocks/stream_block.py
CHANGED
|
@@ -812,10 +812,10 @@ class StreamValue(MutableSequence):
|
|
|
812
812
|
def __reduce__(self):
|
|
813
813
|
try:
|
|
814
814
|
stream_field = self._stream_field
|
|
815
|
-
except AttributeError:
|
|
815
|
+
except AttributeError as e:
|
|
816
816
|
raise PickleError(
|
|
817
817
|
"StreamValue can only be pickled if it is associated with a StreamField"
|
|
818
|
-
)
|
|
818
|
+
) from e
|
|
819
819
|
|
|
820
820
|
return (
|
|
821
821
|
self._deserialize_pickle_value,
|
|
@@ -845,14 +845,6 @@ class StreamBlockAdapter(Adapter):
|
|
|
845
845
|
"minNum": block.meta.min_num,
|
|
846
846
|
"blockCounts": block.meta.block_counts,
|
|
847
847
|
"collapsed": block.meta.collapsed,
|
|
848
|
-
"strings": {
|
|
849
|
-
"MOVE_UP": _("Move up"),
|
|
850
|
-
"MOVE_DOWN": _("Move down"),
|
|
851
|
-
"DRAG": _("Drag"),
|
|
852
|
-
"DUPLICATE": _("Duplicate"),
|
|
853
|
-
"DELETE": _("Delete"),
|
|
854
|
-
"ADD": _("Add"),
|
|
855
|
-
},
|
|
856
848
|
}
|
|
857
849
|
help_text = getattr(block.meta, "help_text", None)
|
|
858
850
|
if help_text:
|
wagtail/blocks/struct_block.py
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import collections
|
|
2
|
+
from typing import Union
|
|
2
3
|
|
|
3
4
|
from django import forms
|
|
5
|
+
from django.core import checks
|
|
4
6
|
from django.core.exceptions import ValidationError
|
|
5
7
|
from django.forms.utils import ErrorList
|
|
6
8
|
from django.template.loader import render_to_string
|
|
7
9
|
from django.utils.functional import cached_property
|
|
8
10
|
from django.utils.html import format_html, format_html_join
|
|
9
11
|
from django.utils.safestring import mark_safe
|
|
12
|
+
from django.utils.translation import gettext_lazy as _
|
|
10
13
|
|
|
11
14
|
from wagtail.admin.staticfiles import versioned_static
|
|
12
15
|
from wagtail.admin.telepath import Adapter, register
|
|
16
|
+
from wagtail.coreutils import safe_snake_case
|
|
13
17
|
|
|
14
18
|
from .base import (
|
|
15
19
|
Block,
|
|
@@ -21,6 +25,7 @@ from .base import (
|
|
|
21
25
|
)
|
|
22
26
|
|
|
23
27
|
__all__ = [
|
|
28
|
+
"BlockGroup",
|
|
24
29
|
"BaseStructBlock",
|
|
25
30
|
"StructBlock",
|
|
26
31
|
"StructValue",
|
|
@@ -70,6 +75,132 @@ class StructBlockValidationError(ValidationError):
|
|
|
70
75
|
return result
|
|
71
76
|
|
|
72
77
|
|
|
78
|
+
@register
|
|
79
|
+
class BlockGroup:
|
|
80
|
+
"""
|
|
81
|
+
A grouping of blocks within a :class:`StructBlock`'s form layout in the
|
|
82
|
+
editing interface. Can be used directly as the ``form_layout`` in
|
|
83
|
+
:class:`StructBlock`.Meta, or nested within another ``BlockGroup``.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def __init__(
|
|
87
|
+
self,
|
|
88
|
+
children: list[Union[str, "BlockGroup"]],
|
|
89
|
+
settings: list[Union[str, "BlockGroup"]] = None,
|
|
90
|
+
heading="",
|
|
91
|
+
classname="",
|
|
92
|
+
help_text="",
|
|
93
|
+
icon="placeholder",
|
|
94
|
+
attrs: dict | None = None,
|
|
95
|
+
label_format: str | None = None,
|
|
96
|
+
):
|
|
97
|
+
"""
|
|
98
|
+
:param children: A list of block names or nested ``BlockGroup`` that will be
|
|
99
|
+
rendered in the main content area.
|
|
100
|
+
:type children: list[str | BlockGroup]
|
|
101
|
+
|
|
102
|
+
:param settings: A list of block names or nested ``BlockGroup`` that will be
|
|
103
|
+
rendered in the collapsible "settings" area that is hidden by default.
|
|
104
|
+
:type settings: list[str | BlockGroup]
|
|
105
|
+
|
|
106
|
+
The following attributes are only used when the ``BlockGroup`` is nested within
|
|
107
|
+
another ``BlockGroup``. For the top-level ``BlockGroup`` used as
|
|
108
|
+
``Meta.form_layout`` in a :class:`StructBlock`, these attributes are ignored in
|
|
109
|
+
favor of the corresponding attributes on ``StructBlock.Meta``.
|
|
110
|
+
|
|
111
|
+
:param heading: The heading label of the collapsible panel for this block
|
|
112
|
+
group. For a top-level group, the ``StructBlock``'s ``label`` will be
|
|
113
|
+
used instead.
|
|
114
|
+
:type heading: str
|
|
115
|
+
|
|
116
|
+
:param classname: Additional CSS class name(s) to add to the block group's main
|
|
117
|
+
content area. To set the group to be initially collapsed, include the
|
|
118
|
+
``collapsed`` class here.
|
|
119
|
+
:type classname: str
|
|
120
|
+
|
|
121
|
+
:param help_text: Help text to display below the block group's heading.
|
|
122
|
+
:type help_text: str
|
|
123
|
+
|
|
124
|
+
:param icon: The name of the icon to display alongside the block group's heading.
|
|
125
|
+
:type icon: str
|
|
126
|
+
|
|
127
|
+
:param attrs: A dictionary of HTML attributes to add to the block group's main content area.
|
|
128
|
+
:type attrs: dict
|
|
129
|
+
|
|
130
|
+
:param label_format: The summary label shown after the ``heading`` when the
|
|
131
|
+
block is collapsed in the editing interface. By default, the value of the
|
|
132
|
+
first child block is shown, but this can be customized by setting a string
|
|
133
|
+
here with block names contained in braces - for example ``label_format = "
|
|
134
|
+
{surname}, {first_name}"``. If you wish to hide the summary label entirely,
|
|
135
|
+
set this to the empty string ``""``.
|
|
136
|
+
:type label_format: str | None
|
|
137
|
+
"""
|
|
138
|
+
self.children = children
|
|
139
|
+
self.settings = settings or []
|
|
140
|
+
self.heading = heading or _("Group")
|
|
141
|
+
self.clean_name = safe_snake_case(self.heading)
|
|
142
|
+
self.classname = classname
|
|
143
|
+
self.help_text = help_text
|
|
144
|
+
self.icon = icon
|
|
145
|
+
self.attrs = attrs or {}
|
|
146
|
+
self.label_format = label_format
|
|
147
|
+
|
|
148
|
+
telepath_adapter_name = "wagtail.blocks.BlockGroup"
|
|
149
|
+
|
|
150
|
+
@cached_property
|
|
151
|
+
def unique_children_and_settings(self):
|
|
152
|
+
# Ensure unique identifiers in the case of multiple BlockGroups with the
|
|
153
|
+
# same headings on the same level, either in children or settings.
|
|
154
|
+
used_names = set()
|
|
155
|
+
|
|
156
|
+
def group_with_unique_names(group):
|
|
157
|
+
results = []
|
|
158
|
+
for child in group:
|
|
159
|
+
base_name = child.clean_name if isinstance(child, BlockGroup) else child
|
|
160
|
+
candidate_name = base_name
|
|
161
|
+
suffix = 0
|
|
162
|
+
while candidate_name in used_names:
|
|
163
|
+
suffix += 1
|
|
164
|
+
candidate_name = "%s%d" % (base_name, suffix)
|
|
165
|
+
results.append((child, candidate_name))
|
|
166
|
+
used_names.add(candidate_name)
|
|
167
|
+
return results
|
|
168
|
+
|
|
169
|
+
children = group_with_unique_names(self.children)
|
|
170
|
+
settings = group_with_unique_names(self.settings)
|
|
171
|
+
return children, settings
|
|
172
|
+
|
|
173
|
+
def get_sorted_block_names(self):
|
|
174
|
+
"""
|
|
175
|
+
Return a flat list of all block names in this ``BlockGroup`` and any
|
|
176
|
+
nested ``BlockGroups`` in the group's list order.
|
|
177
|
+
"""
|
|
178
|
+
block_names = []
|
|
179
|
+
for child in self.children + self.settings:
|
|
180
|
+
if isinstance(child, BlockGroup):
|
|
181
|
+
block_names.extend(child.get_sorted_block_names())
|
|
182
|
+
else:
|
|
183
|
+
block_names.append(child)
|
|
184
|
+
return block_names
|
|
185
|
+
|
|
186
|
+
def js_opts(self):
|
|
187
|
+
children, settings = self.unique_children_and_settings
|
|
188
|
+
return {
|
|
189
|
+
"children": children,
|
|
190
|
+
"settings": settings,
|
|
191
|
+
"heading": self.heading,
|
|
192
|
+
"cleanName": self.clean_name,
|
|
193
|
+
"classname": self.classname,
|
|
194
|
+
"helpText": self.help_text,
|
|
195
|
+
"icon": self.icon,
|
|
196
|
+
"attrs": self.attrs,
|
|
197
|
+
"labelFormat": self.label_format,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
def telepath_pack(self, context):
|
|
201
|
+
return (self.telepath_adapter_name, [self.js_opts()])
|
|
202
|
+
|
|
203
|
+
|
|
73
204
|
class StructValue(collections.OrderedDict):
|
|
74
205
|
"""A class that generates a StructBlock value from provided sub-blocks"""
|
|
75
206
|
|
|
@@ -119,6 +250,17 @@ class BaseStructBlock(Block):
|
|
|
119
250
|
block.set_name(name)
|
|
120
251
|
self.child_blocks[name] = block
|
|
121
252
|
|
|
253
|
+
self.meta.form_layout = self.get_form_layout()
|
|
254
|
+
|
|
255
|
+
# Reorder child_blocks to match form_layout, appending any missing
|
|
256
|
+
# blocks to the end
|
|
257
|
+
sorted_block_names = self.meta.form_layout.get_sorted_block_names()
|
|
258
|
+
missing_block_names = self.child_blocks.keys() - set(sorted_block_names)
|
|
259
|
+
self.child_blocks = collections.OrderedDict(
|
|
260
|
+
(name, self.child_blocks[name])
|
|
261
|
+
for name in (sorted_block_names + list(missing_block_names))
|
|
262
|
+
)
|
|
263
|
+
|
|
122
264
|
@classmethod
|
|
123
265
|
def construct_from_lookup(cls, lookup, child_blocks, **kwargs):
|
|
124
266
|
if child_blocks:
|
|
@@ -335,9 +477,27 @@ class BaseStructBlock(Block):
|
|
|
335
477
|
for name, child_block in self.child_blocks.items():
|
|
336
478
|
errors.extend(child_block.check(**kwargs))
|
|
337
479
|
errors.extend(child_block._check_name(**kwargs))
|
|
480
|
+
errors.extend(self._check_form_layout())
|
|
338
481
|
|
|
339
482
|
return errors
|
|
340
483
|
|
|
484
|
+
def _check_form_layout(self):
|
|
485
|
+
if self.meta.form_template and any(
|
|
486
|
+
isinstance(name, BlockGroup)
|
|
487
|
+
for name in (
|
|
488
|
+
self.meta.form_layout.children + self.meta.form_layout.settings
|
|
489
|
+
)
|
|
490
|
+
):
|
|
491
|
+
return [
|
|
492
|
+
checks.Error(
|
|
493
|
+
f"{self.__class__.__name__}.Meta.form_layout cannot have "
|
|
494
|
+
"nested BlockGroups when using a custom form_template.",
|
|
495
|
+
obj=self,
|
|
496
|
+
id="wagtailcore.E007",
|
|
497
|
+
)
|
|
498
|
+
]
|
|
499
|
+
return []
|
|
500
|
+
|
|
341
501
|
def render_basic(self, value, context=None):
|
|
342
502
|
return format_html(
|
|
343
503
|
"<dl>\n{}\n</dl>",
|
|
@@ -363,24 +523,42 @@ class BaseStructBlock(Block):
|
|
|
363
523
|
return super().get_description() or getattr(self.meta, "help_text", "")
|
|
364
524
|
|
|
365
525
|
def get_form_context(self, value, prefix="", errors=None):
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
526
|
+
children = collections.OrderedDict(
|
|
527
|
+
[
|
|
528
|
+
(
|
|
529
|
+
name,
|
|
530
|
+
PlaceholderBoundBlock(
|
|
531
|
+
block, value.get(name), prefix=f"{prefix}-{name}"
|
|
532
|
+
),
|
|
533
|
+
)
|
|
534
|
+
for name, block in self.child_blocks.items()
|
|
535
|
+
]
|
|
536
|
+
)
|
|
537
|
+
# Move settings blocks into a separate dict for easier access in templates
|
|
538
|
+
settings = collections.OrderedDict(
|
|
539
|
+
[(name, children.pop(name)) for name in self.meta.form_layout.settings]
|
|
540
|
+
)
|
|
541
|
+
context = {
|
|
542
|
+
"children": children,
|
|
543
|
+
"settings": settings,
|
|
378
544
|
"help_text": getattr(self.meta, "help_text", None),
|
|
379
545
|
"classname": self.meta.form_classname,
|
|
380
546
|
"collapsed": self.meta.collapsed,
|
|
381
547
|
"block_definition": self,
|
|
382
548
|
"prefix": prefix,
|
|
383
549
|
}
|
|
550
|
+
return context
|
|
551
|
+
|
|
552
|
+
def get_form_layout(self) -> BlockGroup:
|
|
553
|
+
"""
|
|
554
|
+
Return the :class:`BlockGroup` representing the form layout for this
|
|
555
|
+
``StructBlock``.
|
|
556
|
+
"""
|
|
557
|
+
if (form_layout := self.meta.form_layout) is None:
|
|
558
|
+
return BlockGroup(list(self.child_blocks.keys()))
|
|
559
|
+
if isinstance(form_layout, list):
|
|
560
|
+
return BlockGroup(form_layout)
|
|
561
|
+
return form_layout
|
|
384
562
|
|
|
385
563
|
@cached_property
|
|
386
564
|
def _has_default(self):
|
|
@@ -393,6 +571,7 @@ class BaseStructBlock(Block):
|
|
|
393
571
|
value_class = StructValue
|
|
394
572
|
label_format = None
|
|
395
573
|
collapsed = False
|
|
574
|
+
form_layout: BlockGroup | list[Union[str, "BlockGroup"]] | None = None
|
|
396
575
|
# No icon specified here, because that depends on the purpose that the
|
|
397
576
|
# block is being used for. Feel encouraged to specify an icon in your
|
|
398
577
|
# descendant block type
|
|
@@ -417,6 +596,7 @@ class StructBlockAdapter(Adapter):
|
|
|
417
596
|
"classname": block.meta.form_classname,
|
|
418
597
|
"collapsed": block.meta.collapsed,
|
|
419
598
|
"attrs": block.meta.form_attrs or {},
|
|
599
|
+
"formLayout": block.meta.form_layout,
|
|
420
600
|
}
|
|
421
601
|
|
|
422
602
|
help_text = getattr(block.meta, "help_text", None)
|
wagtail/compat.py
CHANGED
|
@@ -9,10 +9,10 @@ AUTH_USER_MODEL = getattr(settings, "AUTH_USER_MODEL", "auth.User")
|
|
|
9
9
|
# specifying the user model in the FakeORM
|
|
10
10
|
try:
|
|
11
11
|
AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME = AUTH_USER_MODEL.rsplit(".", 1)
|
|
12
|
-
except ValueError:
|
|
12
|
+
except ValueError as e:
|
|
13
13
|
raise ImproperlyConfigured(
|
|
14
14
|
"AUTH_USER_MODEL must be of the form 'app_label.model_name'"
|
|
15
|
-
)
|
|
15
|
+
) from e
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
try:
|
|
@@ -8,7 +8,7 @@ msgid ""
|
|
|
8
8
|
msgstr ""
|
|
9
9
|
"Project-Id-Version: PACKAGE VERSION\n"
|
|
10
10
|
"Report-Msgid-Bugs-To: \n"
|
|
11
|
-
"POT-Creation-Date:
|
|
11
|
+
"POT-Creation-Date: 2026-01-21 18:00+0000\n"
|
|
12
12
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
13
13
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
14
14
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
Binary file
|