wagtail 6.2.2__py3-none-any.whl → 6.3rc2__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 +6 -0
- wagtail/actions/publish_revision.py +3 -3
- wagtail/admin/action_menu.py +5 -3
- wagtail/admin/forms/account.py +1 -1
- wagtail/admin/icons.py +2 -6
- wagtail/admin/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/cy/LC_MESSAGES/django.po +32 -0
- wagtail/admin/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/dv/LC_MESSAGES/django.po +28 -0
- wagtail/admin/locale/en/LC_MESSAGES/django.po +451 -485
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +7 -7
- wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/django.po +150 -0
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +9 -2
- wagtail/admin/locale/ug/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ug/LC_MESSAGES/django.po +3250 -196
- wagtail/admin/localization.py +12 -2
- wagtail/admin/panels/model_utils.py +1 -1
- wagtail/admin/site_summary.py +0 -2
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
- wagtail/admin/static/wagtailadmin/images/email-header.jpg +0 -0
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +12 -0
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/widgets.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/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/staticfiles.py +6 -4
- wagtail/admin/templates/wagtailadmin/account/account.html +42 -59
- wagtail/admin/templates/wagtailadmin/admin_base.html +0 -28
- wagtail/admin/templates/wagtailadmin/bulk_actions/footer.html +1 -1
- wagtail/admin/templates/wagtailadmin/chooser/_search_results.html +7 -5
- wagtail/admin/templates/wagtailadmin/chooser/tables/page_navigate_to_children_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/generic/chooser/results.html +7 -5
- wagtail/admin/templates/wagtailadmin/generic/edit.html +0 -8
- wagtail/admin/templates/wagtailadmin/generic/form.html +60 -17
- wagtail/admin/templates/wagtailadmin/generic/index.html +17 -0
- wagtail/admin/templates/wagtailadmin/generic/index_results.html +9 -35
- wagtail/admin/templates/wagtailadmin/generic/inspect.html +2 -21
- wagtail/admin/templates/wagtailadmin/generic/listing.html +11 -17
- wagtail/admin/templates/wagtailadmin/generic/listing_results.html +19 -1
- wagtail/admin/templates/wagtailadmin/home/account_summary.html +26 -0
- wagtail/admin/templates/wagtailadmin/home/locked_pages.html +28 -18
- wagtail/admin/templates/wagtailadmin/home/recent_edits.html +28 -17
- wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +2 -2
- wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +35 -13
- wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +28 -18
- wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +43 -32
- wagtail/admin/templates/wagtailadmin/home.html +22 -5
- wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -11
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu_item.html +1 -6
- wagtail/admin/templates/wagtailadmin/pages/action_menu/page_locked.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/publish.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_delete.html +12 -6
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html +12 -7
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html +17 -11
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html +15 -9
- wagtail/admin/templates/wagtailadmin/pages/confirm_delete.html +9 -9
- wagtail/admin/templates/wagtailadmin/pages/confirm_move.html +2 -2
- wagtail/admin/templates/wagtailadmin/pages/confirm_unpublish.html +4 -4
- wagtail/admin/templates/wagtailadmin/pages/create.html +15 -34
- wagtail/admin/templates/wagtailadmin/pages/edit.html +15 -30
- wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +6 -0
- wagtail/admin/templates/wagtailadmin/pages/explorable_index_results.html +60 -0
- wagtail/admin/templates/wagtailadmin/pages/index.html +1 -36
- wagtail/admin/templates/wagtailadmin/pages/index_results.html +2 -50
- wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_ordering_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_header_buttons.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +3 -3
- wagtail/admin/templates/wagtailadmin/pages/listing/_pagination.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing.html +24 -0
- wagtail/admin/templates/wagtailadmin/pages/search.html +1 -20
- wagtail/admin/templates/wagtailadmin/pages/search_results.html +27 -25
- wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +0 -1
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +2 -2
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +6 -6
- wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/action_menu/menu.html +14 -0
- wagtail/admin/templates/wagtailadmin/shared/action_menu/menu_item.html +6 -0
- wagtail/admin/templates/wagtailadmin/shared/avatar.html +13 -3
- wagtail/admin/templates/wagtailadmin/shared/header.html +0 -5
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +4 -1
- wagtail/admin/templates/wagtailadmin/shared/pagination_nav.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/locale.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +94 -52
- wagtail/admin/templates/wagtailadmin/{pages/_unsaved_changes_warning.html → shared/unsaved_changes_warning.html} +4 -4
- wagtail/admin/templates/wagtailadmin/shared/usage_summary.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +1 -7
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/listing.html +1 -0
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/{list.html → listing_results.html} +33 -35
- wagtail/admin/templates/wagtailadmin/tables/references_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/create.html +11 -36
- wagtail/admin/templates/wagtailadmin/workflows/create_task.html +0 -38
- wagtail/admin/templates/wagtailadmin/workflows/edit.html +44 -74
- wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +27 -66
- wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -2
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +4 -4
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +15 -11
- wagtail/admin/templates/wagtailadmin/workflows/task_chooser/includes/results.html +7 -5
- wagtail/admin/templatetags/wagtailadmin_tags.py +51 -22
- wagtail/admin/tests/pages/test_content_type_use_view.py +82 -2
- wagtail/admin/tests/pages/test_edit_page.py +70 -0
- wagtail/admin/tests/pages/test_explorer_view.py +65 -4
- wagtail/admin/tests/pages/test_page_search.py +8 -7
- wagtail/admin/tests/pages/test_page_usage.py +3 -1
- wagtail/admin/tests/pages/test_preview.py +208 -63
- wagtail/admin/tests/pages/test_reorder_page.py +91 -1
- wagtail/admin/tests/pages/test_view_draft.py +32 -1
- wagtail/admin/tests/pages/test_workflow_history.py +288 -7
- wagtail/admin/tests/test_account_management.py +23 -3
- wagtail/admin/tests/test_audit_log.py +24 -2
- wagtail/admin/tests/test_collections_views.py +17 -5
- wagtail/admin/tests/test_dashboard.py +1 -1
- wagtail/admin/tests/test_edit_handlers.py +3 -2
- wagtail/admin/tests/test_icon_sprite.py +4 -0
- wagtail/admin/tests/test_privacy.py +5 -19
- wagtail/admin/tests/test_reports_views.py +1 -1
- wagtail/admin/tests/test_site_summary.py +3 -3
- wagtail/admin/tests/test_templatetags.py +27 -3
- wagtail/admin/tests/test_upgrade_notification.py +71 -18
- wagtail/admin/tests/test_views.py +2 -2
- wagtail/admin/tests/test_views_generic.py +13 -0
- wagtail/admin/tests/test_widgets.py +3 -3
- wagtail/admin/tests/test_workflows.py +172 -27
- wagtail/admin/tests/tests.py +1 -1
- wagtail/admin/tests/viewsets/test_model_viewset.py +55 -3
- wagtail/admin/ui/side_panels.py +19 -0
- wagtail/admin/ui/sidebar.py +4 -3
- wagtail/admin/ui/tables/__init__.py +14 -1
- wagtail/admin/ui/tables/pages.py +6 -1
- wagtail/admin/urls/pages.py +10 -1
- wagtail/admin/urls/workflows.py +6 -1
- wagtail/admin/views/account.py +5 -1
- wagtail/admin/views/collections.py +0 -2
- wagtail/admin/views/generic/base.py +118 -1
- wagtail/admin/views/generic/history.py +158 -26
- wagtail/admin/views/generic/models.py +113 -99
- wagtail/admin/views/home.py +24 -9
- wagtail/admin/views/page_privacy.py +54 -30
- wagtail/admin/views/pages/history.py +11 -4
- wagtail/admin/views/pages/listing.py +76 -89
- wagtail/admin/views/pages/preview.py +1 -1
- wagtail/admin/views/pages/search.py +27 -71
- wagtail/admin/views/pages/usage.py +63 -24
- wagtail/admin/views/pages/utils.py +4 -3
- wagtail/admin/views/reports/base.py +0 -6
- wagtail/admin/views/workflows.py +67 -25
- wagtail/admin/viewsets/model.py +4 -3
- wagtail/admin/widgets/chooser.py +2 -1
- wagtail/api/v2/tests/test_pages.py +15 -2
- wagtail/blocks/field_block.py +15 -3
- wagtail/blocks/static_block.py +3 -0
- wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.po +29 -1
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +15 -11
- wagtail/contrib/forms/templates/wagtailforms/confirm_delete.html +1 -0
- wagtail/contrib/forms/templates/wagtailforms/index.html +1 -1
- wagtail/contrib/forms/templates/wagtailforms/index_results.html +1 -1
- wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +2 -1
- wagtail/contrib/forms/templates/wagtailforms/panels/form_responses_panel.html +2 -2
- wagtail/contrib/forms/tests/test_views.py +234 -35
- wagtail/contrib/forms/utils.py +8 -14
- wagtail/contrib/forms/views.py +72 -27
- wagtail/contrib/frontend_cache/backends/azure.py +1 -1
- wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
- wagtail/contrib/frontend_cache/backends/dummy.py +11 -0
- wagtail/contrib/frontend_cache/tests.py +31 -37
- wagtail/contrib/frontend_cache/utils.py +12 -5
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +16 -1
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +20 -24
- wagtail/contrib/redirects/models.py +16 -1
- wagtail/contrib/redirects/signal_handlers.py +18 -3
- wagtail/contrib/redirects/templates/wagtailredirects/add.html +5 -16
- wagtail/contrib/redirects/templates/wagtailredirects/import_summary.html +1 -1
- wagtail/contrib/redirects/tests/test_redirects.py +49 -6
- wagtail/contrib/redirects/tests/test_signal_handlers.py +42 -1
- wagtail/contrib/redirects/views.py +27 -3
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +60 -1
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +12 -18
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +5 -8
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +15 -10
- wagtail/contrib/search_promotions/tests.py +13 -2
- wagtail/contrib/search_promotions/views.py +15 -3
- wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -10
- wagtail/contrib/settings/templates/wagtailsettings/edit.html +12 -45
- wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.po +13 -1
- wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.po +3 -0
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/simple_translation/tests/test_views.py +51 -0
- wagtail/contrib/simple_translation/wagtail_hooks.py +16 -11
- wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.po +27 -1
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/blocks.py +25 -0
- wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.po +12 -1
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/contrib/typed_table_block/tests.py +24 -1
- wagtail/coreutils.py +5 -11
- wagtail/documents/admin_urls.py +2 -2
- wagtail/documents/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/cy/LC_MESSAGES/django.po +10 -0
- wagtail/documents/locale/en/LC_MESSAGES/django.po +61 -76
- wagtail/documents/migrations/0014_alter_document_file_size.py +18 -0
- wagtail/documents/models.py +1 -1
- wagtail/documents/rich_text/__init__.py +1 -3
- wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_tags.html +5 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_delete.html +11 -5
- wagtail/documents/templates/wagtaildocs/documents/add.html +13 -41
- wagtail/documents/templates/wagtaildocs/documents/edit.html +28 -56
- wagtail/documents/templates/wagtaildocs/documents/index.html +1 -4
- wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +2 -2
- wagtail/documents/templates/wagtaildocs/multiple/add.html +36 -41
- wagtail/documents/tests/test_admin_views.py +64 -6
- wagtail/documents/tests/test_site_summary.py +3 -3
- wagtail/documents/views/documents.py +103 -113
- wagtail/documents/views/multiple.py +19 -1
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/oembed_providers.py +9 -19
- wagtail/fields.py +43 -27
- wagtail/images/admin_urls.py +2 -2
- wagtail/images/blocks.py +230 -2
- wagtail/images/fields.py +17 -29
- wagtail/images/image_operations.py +1 -1
- wagtail/images/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/cy/LC_MESSAGES/django.po +128 -1
- wagtail/images/locale/en/LC_MESSAGES/django.po +119 -129
- wagtail/images/migrations/0025_alter_image_file_alter_rendition_file.py +36 -43
- wagtail/images/migrations/0027_image_description.py +20 -0
- wagtail/images/models.py +120 -45
- wagtail/images/rich_text/__init__.py +1 -3
- wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
- wagtail/images/static/wagtailimages/js/image-block.js +1 -0
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_tags.html +5 -1
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_delete.html +11 -5
- wagtail/images/templates/wagtailimages/chooser/results.html +2 -2
- wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +2 -2
- wagtail/images/templates/wagtailimages/images/_file_field.html +2 -2
- wagtail/images/templates/wagtailimages/images/add.html +13 -31
- wagtail/images/templates/wagtailimages/images/edit.html +53 -82
- wagtail/images/templates/wagtailimages/images/index.html +1 -4
- wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
- wagtail/images/templates/wagtailimages/multiple/add.html +40 -47
- wagtail/images/templates/wagtailimages/widgets/image.html +5 -0
- wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
- wagtail/images/tests/test_admin_views.py +70 -10
- wagtail/images/tests/test_blocks.py +367 -1
- wagtail/images/tests/test_image_operations.py +23 -0
- wagtail/images/tests/test_models.py +20 -0
- wagtail/images/tests/test_signal_handlers.py +99 -95
- wagtail/images/tests/test_site_summary.py +3 -3
- wagtail/images/tests/test_templatetags.py +11 -7
- wagtail/images/tests/tests.py +4 -0
- wagtail/images/views/images.py +103 -104
- wagtail/images/views/multiple.py +17 -1
- wagtail/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/cy/LC_MESSAGES/django.po +3 -0
- wagtail/locale/en/LC_MESSAGES/django.po +137 -125
- wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sl/LC_MESSAGES/django.po +3 -0
- wagtail/locales/locale/en/LC_MESSAGES/django.po +8 -8
- wagtail/locales/views.py +4 -1
- wagtail/migrations/0089_log_entry_data_json_null_to_object.py +1 -7
- wagtail/models/__init__.py +122 -14
- wagtail/models/audit_log.py +1 -3
- wagtail/models/i18n.py +1 -2
- wagtail/project_template/Dockerfile +3 -3
- wagtail/project_template/requirements.txt +2 -2
- wagtail/query.py +17 -4
- wagtail/rich_text/__init__.py +2 -3
- wagtail/rich_text/pages.py +2 -4
- wagtail/rich_text/rewriters.py +2 -2
- wagtail/search/backends/database/mysql/query.py +3 -3
- wagtail/search/backends/database/sqlite/query.py +6 -6
- wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/sites/locale/en/LC_MESSAGES/django.po +6 -6
- wagtail/sites/views.py +0 -1
- wagtail/snippets/action_menu.py +14 -4
- wagtail/snippets/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/cy/LC_MESSAGES/django.po +73 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +27 -33
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
- wagtail/snippets/templates/wagtailsnippets/bulk_actions/confirm_bulk_delete.html +5 -3
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/locked.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -11
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu_item.html +1 -6
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -18
- wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -14
- wagtail/snippets/templates/wagtailsnippets/snippets/index.html +2 -5
- wagtail/snippets/tests/test_preview.py +193 -61
- wagtail/snippets/tests/test_snippets.py +247 -38
- wagtail/snippets/tests/test_usage.py +5 -0
- wagtail/snippets/tests/test_viewset.py +25 -9
- wagtail/snippets/tests/test_workflows.py +232 -19
- wagtail/snippets/views/snippets.py +1 -10
- wagtail/test/numberformat.py +104 -0
- wagtail/test/settings.py +10 -0
- wagtail/test/settings_ui.py +2 -0
- wagtail/test/testapp/migrations/0010_alter_customimage_file_and_more.py +71 -78
- wagtail/test/testapp/migrations/0040_nocreatablesubpagetypespage_nosubpagetypespage.py +54 -0
- wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py +17 -0
- wagtail/test/testapp/migrations/0042_alter_customdocument_file_size_and_more.py +28 -0
- wagtail/test/testapp/migrations/0043_customimage_description.py +41 -0
- wagtail/test/testapp/migrations/0044_custompreviewsizesmodel_custompreviewsizespage.py +52 -0
- wagtail/test/testapp/migrations/0045_alter_streampage_body.py +52 -0
- wagtail/test/testapp/models.py +62 -4
- wagtail/test/testapp/rich_text.py +2 -2
- wagtail/test/testapp/templates/tests/form_page_landing.html +2 -1
- wagtail/test/testapp/urls.py +5 -0
- wagtail/test/testapp/views.py +5 -0
- wagtail/test/utils/page_tests.py +5 -5
- wagtail/test/utils/template_tests.py +2 -2
- wagtail/tests/test_blocks.py +15 -0
- wagtail/tests/test_page_permissions.py +109 -0
- wagtail/tests/test_revision_model.py +27 -0
- wagtail/tests/test_signals.py +21 -2
- wagtail/tests/test_tests.py +30 -0
- wagtail/users/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/cy/LC_MESSAGES/django.po +118 -1
- wagtail/users/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/dv/LC_MESSAGES/django.po +3 -0
- wagtail/users/locale/en/LC_MESSAGES/django.po +89 -113
- wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sl/LC_MESSAGES/django.po +3 -0
- wagtail/users/migrations/0014_userprofile_contrast.py +23 -0
- wagtail/users/models.py +11 -0
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_assign_role.html +5 -1
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_delete.html +5 -1
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_set_active_state.html +5 -1
- wagtail/users/templates/wagtailusers/groups/create.html +19 -17
- wagtail/users/templates/wagtailusers/groups/edit.html +2 -40
- wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +1 -62
- wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +0 -1
- wagtail/users/templates/wagtailusers/users/create.html +46 -50
- wagtail/users/templates/wagtailusers/users/edit.html +45 -62
- wagtail/users/templates/wagtailusers/users/index.html +1 -4
- wagtail/users/templatetags/wagtailusers_tags.py +1 -5
- wagtail/users/tests/test_admin_views.py +85 -66
- wagtail/users/views/groups.py +4 -1
- wagtail/users/views/users.py +2 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/METADATA +6 -6
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/RECORD +378 -367
- wagtail/admin/static/wagtailadmin/js/preview-panel.js +0 -2
- wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +0 -11
- wagtail/admin/templates/wagtailadmin/generic/history_results.html +0 -1
- wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +0 -3
- wagtail/admin/templates/wagtailadmin/pages/usage_results.html +0 -6
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/index.html +0 -17
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/results.html +0 -17
- wagtail/admin/templates/wagtailadmin/workflows/usage.html +0 -44
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/LICENSE +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/WHEEL +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/entry_points.txt +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/top_level.txt +0 -0
|
@@ -40,8 +40,8 @@ class TestModelViewSetGroup(WagtailTestUtils, TestCase):
|
|
|
40
40
|
response,
|
|
41
41
|
'"name": "tests", "label": "Tests", "icon_name": "folder-open-inverse"',
|
|
42
42
|
)
|
|
43
|
-
#
|
|
44
|
-
self.assertContains(response, "
|
|
43
|
+
# Capitalized-first from verbose_name_plural
|
|
44
|
+
self.assertContains(response, "JSON stream models")
|
|
45
45
|
self.assertContains(response, reverse("streammodel:index"))
|
|
46
46
|
self.assertEqual(reverse("streammodel:index"), "/admin/streammodel/")
|
|
47
47
|
# Set on class
|
|
@@ -81,7 +81,7 @@ class TestModelViewSetGroup(WagtailTestUtils, TestCase):
|
|
|
81
81
|
)
|
|
82
82
|
|
|
83
83
|
# The menu item for the model is shown
|
|
84
|
-
self.assertContains(response, "
|
|
84
|
+
self.assertContains(response, "JSON stream models")
|
|
85
85
|
self.assertContains(response, reverse("streammodel:index"))
|
|
86
86
|
self.assertEqual(reverse("streammodel:index"), "/admin/streammodel/")
|
|
87
87
|
|
|
@@ -451,6 +451,7 @@ class TestSearchIndexView(WagtailTestUtils, TestCase):
|
|
|
451
451
|
|
|
452
452
|
def test_search_disabled(self):
|
|
453
453
|
response = self.get("fctoy_alt1", {"q": "ork"})
|
|
454
|
+
self.assertFalse(response.context.get("search_form"))
|
|
454
455
|
self.assertContains(response, "Forky")
|
|
455
456
|
self.assertContains(response, "Buzz Lightyear")
|
|
456
457
|
self.assertNotContains(response, "There are 2 matches")
|
|
@@ -1043,6 +1044,11 @@ class TestHistoryView(WagtailTestUtils, TestCase):
|
|
|
1043
1044
|
for rendered_row, expected_row in zip(rendered_rows, expected):
|
|
1044
1045
|
self.assertSequenceEqual(rendered_row, expected_row)
|
|
1045
1046
|
|
|
1047
|
+
# History view is not searchable
|
|
1048
|
+
input = soup.select_one("input#id_q")
|
|
1049
|
+
self.assertIsNone(input)
|
|
1050
|
+
self.assertFalse(response.context.get("search_form"))
|
|
1051
|
+
|
|
1046
1052
|
def test_action_filter(self):
|
|
1047
1053
|
response = self.client.get(self.url)
|
|
1048
1054
|
self.assertEqual(response.status_code, 200)
|
|
@@ -1235,12 +1241,22 @@ class TestUsageView(WagtailTestUtils, TestCase):
|
|
|
1235
1241
|
link = tds[0].select_one("a")
|
|
1236
1242
|
self.assertIsNotNone(link)
|
|
1237
1243
|
self.assertEqual(link.attrs.get("href"), tbx_edit_url)
|
|
1244
|
+
content_path_link = tds[-1].select_one("a")
|
|
1245
|
+
self.assertEqual(
|
|
1246
|
+
content_path_link.attrs.get("href"),
|
|
1247
|
+
tbx_edit_url + "#:w:contentpath=cascading_toy",
|
|
1248
|
+
)
|
|
1238
1249
|
|
|
1239
1250
|
# Link to referrer's edit view with parameters for the specific field
|
|
1240
1251
|
link = tds[2].select_one("a")
|
|
1241
1252
|
self.assertIsNotNone(link)
|
|
1242
1253
|
self.assertIn(tbx_edit_url, link.attrs.get("href"))
|
|
1243
1254
|
|
|
1255
|
+
# Usage view is not searchable
|
|
1256
|
+
input = soup.select_one("input#id_q")
|
|
1257
|
+
self.assertIsNone(input)
|
|
1258
|
+
self.assertFalse(response.context.get("search_form"))
|
|
1259
|
+
|
|
1244
1260
|
def test_usage_without_permission(self):
|
|
1245
1261
|
self.user.is_superuser = False
|
|
1246
1262
|
self.user.save()
|
|
@@ -1817,3 +1833,39 @@ class TestDefaultMessages(WagtailTestUtils, TestCase):
|
|
|
1817
1833
|
response,
|
|
1818
1834
|
escape(f"Feature complete toy '{self.object}' deleted."),
|
|
1819
1835
|
)
|
|
1836
|
+
|
|
1837
|
+
|
|
1838
|
+
class TestHeaderButtons(WagtailTestUtils, TestCase):
|
|
1839
|
+
def setUp(self):
|
|
1840
|
+
self.user = self.login()
|
|
1841
|
+
|
|
1842
|
+
@classmethod
|
|
1843
|
+
def setUpTestData(cls):
|
|
1844
|
+
cls.object = FeatureCompleteToy.objects.create(name="Test Toy")
|
|
1845
|
+
cls.edit_url = reverse(
|
|
1846
|
+
"feature_complete_toy:edit", args=(quote(cls.object.pk),)
|
|
1847
|
+
)
|
|
1848
|
+
cls.copy_url = reverse(
|
|
1849
|
+
"feature_complete_toy:copy", args=(quote(cls.object.pk),)
|
|
1850
|
+
)
|
|
1851
|
+
cls.delete_url = reverse(
|
|
1852
|
+
"feature_complete_toy:delete", args=(quote(cls.object.pk),)
|
|
1853
|
+
)
|
|
1854
|
+
cls.inspect_url = reverse(
|
|
1855
|
+
"feature_complete_toy:inspect", args=(quote(cls.object.pk),)
|
|
1856
|
+
)
|
|
1857
|
+
|
|
1858
|
+
def test_header_buttons_in_edit_view(self):
|
|
1859
|
+
response = self.client.get(self.edit_url)
|
|
1860
|
+
self.assertEqual(response.status_code, 200)
|
|
1861
|
+
soup = self.get_soup(response.content)
|
|
1862
|
+
header_buttons = soup.select(".w-slim-header .w-dropdown a")
|
|
1863
|
+
expected_buttons = [
|
|
1864
|
+
("Copy", self.copy_url),
|
|
1865
|
+
("Delete", self.delete_url),
|
|
1866
|
+
("Inspect", self.inspect_url),
|
|
1867
|
+
]
|
|
1868
|
+
self.assertEqual(
|
|
1869
|
+
[(a.text.strip(), a.get("href")) for a in header_buttons],
|
|
1870
|
+
expected_buttons,
|
|
1871
|
+
)
|
wagtail/admin/ui/side_panels.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
1
4
|
from django.urls import reverse
|
|
2
5
|
from django.utils.text import capfirst
|
|
3
6
|
from django.utils.translation import gettext_lazy, ngettext
|
|
@@ -6,6 +9,7 @@ from wagtail import hooks
|
|
|
6
9
|
from wagtail.admin.ui.components import Component
|
|
7
10
|
from wagtail.admin.userbar import AccessibilityItem
|
|
8
11
|
from wagtail.models import DraftStateMixin, LockableMixin, Page, ReferenceIndex
|
|
12
|
+
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
class BaseSidePanel(Component):
|
|
@@ -350,8 +354,23 @@ class PreviewSidePanel(BaseSidePanel):
|
|
|
350
354
|
super().__init__(object, request)
|
|
351
355
|
self.preview_url = preview_url
|
|
352
356
|
|
|
357
|
+
@property
|
|
358
|
+
def auto_update_interval(self):
|
|
359
|
+
if hasattr(settings, "WAGTAIL_AUTO_UPDATE_PREVIEW"):
|
|
360
|
+
warnings.warn(
|
|
361
|
+
"`WAGTAIL_AUTO_UPDATE_PREVIEW` is deprecated. "
|
|
362
|
+
"Set `WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL = 0` to disable "
|
|
363
|
+
"auto-update for previews.",
|
|
364
|
+
RemovedInWagtail70Warning,
|
|
365
|
+
)
|
|
366
|
+
if not settings.WAGTAIL_AUTO_UPDATE_PREVIEW:
|
|
367
|
+
return 0
|
|
368
|
+
|
|
369
|
+
return getattr(settings, "WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL", 500)
|
|
370
|
+
|
|
353
371
|
def get_context_data(self, parent_context):
|
|
354
372
|
context = super().get_context_data(parent_context)
|
|
355
373
|
context["preview_url"] = self.preview_url
|
|
356
374
|
context["has_multiple_modes"] = len(self.object.preview_modes) > 1
|
|
375
|
+
context["auto_update_interval"] = self.auto_update_interval
|
|
357
376
|
return context
|
wagtail/admin/ui/sidebar.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Any
|
|
2
3
|
from warnings import warn
|
|
3
4
|
|
|
4
5
|
from django import forms
|
|
@@ -152,7 +153,7 @@ class SubMenuItem(MenuItem):
|
|
|
152
153
|
self,
|
|
153
154
|
name: str,
|
|
154
155
|
label: str,
|
|
155
|
-
menu_items:
|
|
156
|
+
menu_items: list[MenuItem],
|
|
156
157
|
icon_name: str = "",
|
|
157
158
|
classname: str = "",
|
|
158
159
|
classnames: str = "",
|
|
@@ -262,7 +263,7 @@ class SearchModule:
|
|
|
262
263
|
@adapter("wagtail.sidebar.MainMenuModule", base=BaseSidebarAdapter)
|
|
263
264
|
class MainMenuModule:
|
|
264
265
|
def __init__(
|
|
265
|
-
self, menu_items:
|
|
266
|
+
self, menu_items: list[MenuItem], account_menu_items: list[MenuItem], user
|
|
266
267
|
):
|
|
267
268
|
self.menu_items = menu_items
|
|
268
269
|
self.account_menu_items = account_menu_items
|
|
@@ -6,6 +6,7 @@ from collections.abc import Mapping
|
|
|
6
6
|
from django.contrib.admin.utils import quote
|
|
7
7
|
from django.forms import MediaDefiningClass
|
|
8
8
|
from django.template.loader import get_template
|
|
9
|
+
from django.templatetags.l10n import unlocalize
|
|
9
10
|
from django.urls import reverse
|
|
10
11
|
from django.utils.functional import cached_property
|
|
11
12
|
from django.utils.text import capfirst
|
|
@@ -156,7 +157,13 @@ class Column(BaseColumn):
|
|
|
156
157
|
|
|
157
158
|
def get_cell_context_data(self, instance, parent_context):
|
|
158
159
|
context = super().get_cell_context_data(instance, parent_context)
|
|
159
|
-
|
|
160
|
+
value = self.get_value(instance)
|
|
161
|
+
if isinstance(value, int) and not isinstance(value, bool):
|
|
162
|
+
# To prevent errors arising from USE_THOUSAND_SEPARATOR, we require all numbers output
|
|
163
|
+
# on templates to be explicitly localized or unlocalized. For numeric table cells, we
|
|
164
|
+
# unlocalize them by default; developers may subclass Column to obtain formatted numbers.
|
|
165
|
+
value = unlocalize(value)
|
|
166
|
+
context["value"] = value
|
|
160
167
|
return context
|
|
161
168
|
|
|
162
169
|
|
|
@@ -272,6 +279,12 @@ class BooleanColumn(Column):
|
|
|
272
279
|
|
|
273
280
|
cell_template_name = "wagtailadmin/tables/boolean_cell.html"
|
|
274
281
|
|
|
282
|
+
def get_value(self, instance):
|
|
283
|
+
value = super().get_value(instance)
|
|
284
|
+
if value is None:
|
|
285
|
+
return None
|
|
286
|
+
return bool(value)
|
|
287
|
+
|
|
275
288
|
|
|
276
289
|
class LiveStatusTagColumn(StatusTagColumn):
|
|
277
290
|
"""Represents a live/draft status tag"""
|
wagtail/admin/ui/tables/pages.py
CHANGED
|
@@ -56,6 +56,8 @@ class ParentPageColumn(Column):
|
|
|
56
56
|
cell_template_name = "wagtailadmin/pages/listing/_parent_page_cell.html"
|
|
57
57
|
|
|
58
58
|
def get_value(self, instance):
|
|
59
|
+
if parent := getattr(instance, "_parent_page", None):
|
|
60
|
+
return parent
|
|
59
61
|
return instance.get_parent()
|
|
60
62
|
|
|
61
63
|
|
|
@@ -92,7 +94,10 @@ class NavigateToChildrenColumn(BaseColumn):
|
|
|
92
94
|
return context
|
|
93
95
|
|
|
94
96
|
def render_header_html(self, parent_context):
|
|
95
|
-
|
|
97
|
+
# This column has no header, as the cell's function will vary between "explore child pages"
|
|
98
|
+
# and "add child page", and this link provides all the signposting needed. Render it as a
|
|
99
|
+
# <td> rather than <th> as headings cannot be empty (https://dequeuniversity.com/rules/axe/4.9/empty-table-header).
|
|
100
|
+
return mark_safe("<td></td>")
|
|
96
101
|
|
|
97
102
|
|
|
98
103
|
class PageTable(Table):
|
wagtail/admin/urls/pages.py
CHANGED
|
@@ -36,6 +36,11 @@ urlpatterns = [
|
|
|
36
36
|
usage.ContentTypeUseView.as_view(),
|
|
37
37
|
name="type_use",
|
|
38
38
|
),
|
|
39
|
+
path(
|
|
40
|
+
"usage/<slug:content_type_app_name>/<slug:content_type_model_name>/results/",
|
|
41
|
+
usage.ContentTypeUseView.as_view(results_only=True),
|
|
42
|
+
name="type_use_results",
|
|
43
|
+
),
|
|
39
44
|
path("<int:page_id>/usage/", usage.UsageView.as_view(), name="usage"),
|
|
40
45
|
path("<int:page_id>/edit/", edit.EditView.as_view(), name="edit"),
|
|
41
46
|
path(
|
|
@@ -53,7 +58,11 @@ urlpatterns = [
|
|
|
53
58
|
name="convert_alias",
|
|
54
59
|
),
|
|
55
60
|
path("search/", search.SearchView.as_view(), name="search"),
|
|
56
|
-
path(
|
|
61
|
+
path(
|
|
62
|
+
"search/results/",
|
|
63
|
+
search.SearchView.as_view(results_only=True),
|
|
64
|
+
name="search_results",
|
|
65
|
+
),
|
|
57
66
|
path("<int:page_to_move_id>/move/", move.move_choose_destination, name="move"),
|
|
58
67
|
path(
|
|
59
68
|
"<int:page_to_move_id>/move/<int:destination_id>/confirm/",
|
wagtail/admin/urls/workflows.py
CHANGED
|
@@ -14,7 +14,12 @@ urlpatterns = [
|
|
|
14
14
|
path("enable/<int:pk>/", workflows.enable_workflow, name="enable"),
|
|
15
15
|
path("disable/<int:pk>/", workflows.Disable.as_view(), name="disable"),
|
|
16
16
|
path("edit/<int:pk>/", workflows.Edit.as_view(), name="edit"),
|
|
17
|
-
path("usage/<int:pk>/", workflows.
|
|
17
|
+
path("usage/<int:pk>/", workflows.WorkflowUsageView.as_view(), name="usage"),
|
|
18
|
+
path(
|
|
19
|
+
"usage/<int:pk>/results/",
|
|
20
|
+
workflows.WorkflowUsageView.as_view(results_only=True),
|
|
21
|
+
name="usage_results",
|
|
22
|
+
),
|
|
18
23
|
path("remove/<int:page_pk>/", workflows.remove_workflow, name="remove"),
|
|
19
24
|
path(
|
|
20
25
|
"remove/<int:page_pk>/<int:workflow_pk>/",
|
wagtail/admin/views/account.py
CHANGED
|
@@ -31,7 +31,7 @@ from wagtail.admin.localization import (
|
|
|
31
31
|
get_available_admin_languages,
|
|
32
32
|
get_available_admin_time_zones,
|
|
33
33
|
)
|
|
34
|
-
from wagtail.admin.views.generic import WagtailAdminTemplateMixin
|
|
34
|
+
from wagtail.admin.views.generic import EditView, WagtailAdminTemplateMixin
|
|
35
35
|
from wagtail.log_actions import log
|
|
36
36
|
from wagtail.users.models import UserProfile
|
|
37
37
|
from wagtail.utils.loading import get_custom_form
|
|
@@ -239,6 +239,10 @@ class AccountView(WagtailAdminTemplateMixin, TemplateView):
|
|
|
239
239
|
context["menu_items"] = self.get_menu_items()
|
|
240
240
|
context["media"] = self.get_media(panels)
|
|
241
241
|
context["user"] = self.request.user
|
|
242
|
+
# Remove these when this view is refactored to a generic.EditView subclass.
|
|
243
|
+
# Avoid defining new translatable strings.
|
|
244
|
+
context["submit_button_label"] = EditView.submit_button_label
|
|
245
|
+
context["submit_button_active_label"] = EditView.submit_button_active_label
|
|
242
246
|
return context
|
|
243
247
|
|
|
244
248
|
def get_panels(self):
|
|
@@ -30,7 +30,6 @@ class Index(IndexView):
|
|
|
30
30
|
accessor="1",
|
|
31
31
|
)
|
|
32
32
|
]
|
|
33
|
-
_show_breadcrumbs = True
|
|
34
33
|
|
|
35
34
|
def get_queryset(self):
|
|
36
35
|
return self.permission_policy.instances_user_has_any_permission_for(
|
|
@@ -76,7 +75,6 @@ class Edit(EditView):
|
|
|
76
75
|
template_name = "wagtailadmin/collections/edit.html"
|
|
77
76
|
success_message = gettext_lazy("Collection '%(object)s' updated.")
|
|
78
77
|
error_message = gettext_lazy("The collection could not be saved due to errors.")
|
|
79
|
-
delete_item_label = gettext_lazy("Delete collection")
|
|
80
78
|
edit_url_name = "wagtailadmin_collections:edit"
|
|
81
79
|
index_url_name = "wagtailadmin_collections:index"
|
|
82
80
|
delete_url_name = "wagtailadmin_collections:delete"
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import warnings
|
|
1
2
|
from collections import namedtuple
|
|
2
3
|
|
|
3
4
|
from django.contrib.admin.utils import quote, unquote
|
|
4
5
|
from django.core.exceptions import ImproperlyConfigured
|
|
5
6
|
from django.db import models
|
|
7
|
+
from django.db.models import Q
|
|
6
8
|
from django.shortcuts import get_object_or_404, redirect
|
|
7
9
|
from django.urls import reverse, reverse_lazy
|
|
8
10
|
from django.utils.formats import date_format
|
|
@@ -20,9 +22,12 @@ from django_filters.filters import (
|
|
|
20
22
|
)
|
|
21
23
|
|
|
22
24
|
from wagtail.admin import messages
|
|
25
|
+
from wagtail.admin.forms.search import SearchForm
|
|
23
26
|
from wagtail.admin.ui.tables import Column, Table
|
|
24
27
|
from wagtail.admin.utils import get_valid_next_url_from_request
|
|
25
28
|
from wagtail.admin.widgets.button import ButtonWithDropdown
|
|
29
|
+
from wagtail.search.backends import get_search_backend
|
|
30
|
+
from wagtail.search.index import class_is_indexed
|
|
26
31
|
from wagtail.utils.utils import flatten_choices
|
|
27
32
|
|
|
28
33
|
|
|
@@ -191,8 +196,14 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
191
196
|
index_url_name = None
|
|
192
197
|
index_results_url_name = None
|
|
193
198
|
page_kwarg = "p"
|
|
199
|
+
is_searchable = None # Subclasses must explicitly set this to True to enable search
|
|
200
|
+
search_kwarg = "q"
|
|
201
|
+
search_fields = None
|
|
202
|
+
search_backend_name = "default"
|
|
194
203
|
default_ordering = None
|
|
195
204
|
filterset_class = None
|
|
205
|
+
verbose_name_plural = None
|
|
206
|
+
_show_breadcrumbs = True
|
|
196
207
|
|
|
197
208
|
def get_template_names(self):
|
|
198
209
|
if self.results_only:
|
|
@@ -202,6 +213,74 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
202
213
|
else:
|
|
203
214
|
return super().get_template_names()
|
|
204
215
|
|
|
216
|
+
def get_breadcrumbs_items(self):
|
|
217
|
+
return self.breadcrumbs_items + [
|
|
218
|
+
{
|
|
219
|
+
"url": "",
|
|
220
|
+
"label": self.get_page_title(),
|
|
221
|
+
"sublabel": self.get_page_subtitle(),
|
|
222
|
+
},
|
|
223
|
+
]
|
|
224
|
+
|
|
225
|
+
def get_search_form(self):
|
|
226
|
+
if not self.is_searchable:
|
|
227
|
+
return None
|
|
228
|
+
|
|
229
|
+
if self.search_kwarg in self.request.GET:
|
|
230
|
+
return SearchForm(self.request.GET)
|
|
231
|
+
|
|
232
|
+
return SearchForm()
|
|
233
|
+
|
|
234
|
+
@cached_property
|
|
235
|
+
def search_form(self):
|
|
236
|
+
return self.get_search_form()
|
|
237
|
+
|
|
238
|
+
@cached_property
|
|
239
|
+
def search_query(self):
|
|
240
|
+
if self.search_form and self.search_form.is_valid():
|
|
241
|
+
return self.search_form.cleaned_data[self.search_kwarg]
|
|
242
|
+
return ""
|
|
243
|
+
|
|
244
|
+
@cached_property
|
|
245
|
+
def is_searching(self):
|
|
246
|
+
return bool(self.search_query)
|
|
247
|
+
|
|
248
|
+
def search_queryset(self, queryset):
|
|
249
|
+
if not self.is_searching:
|
|
250
|
+
return queryset
|
|
251
|
+
|
|
252
|
+
# Use Wagtail Search if the model is indexed and a search backend is defined.
|
|
253
|
+
# Django ORM can still be used on an indexed model by unsetting
|
|
254
|
+
# search_backend_name and defining search_fields on the view.
|
|
255
|
+
if class_is_indexed(queryset.model) and self.search_backend_name:
|
|
256
|
+
search_backend = get_search_backend(self.search_backend_name)
|
|
257
|
+
if queryset.model.get_autocomplete_search_fields():
|
|
258
|
+
return search_backend.autocomplete(
|
|
259
|
+
self.search_query,
|
|
260
|
+
queryset,
|
|
261
|
+
fields=self.search_fields,
|
|
262
|
+
order_by_relevance=(not self.is_explicitly_ordered),
|
|
263
|
+
)
|
|
264
|
+
else:
|
|
265
|
+
# fall back on non-autocompleting search
|
|
266
|
+
warnings.warn(
|
|
267
|
+
f"{queryset.model} is defined as Indexable but does not specify "
|
|
268
|
+
"any AutocompleteFields. Searches within the admin will only "
|
|
269
|
+
"respond to complete words.",
|
|
270
|
+
category=RuntimeWarning,
|
|
271
|
+
)
|
|
272
|
+
return search_backend.search(
|
|
273
|
+
self.search_query,
|
|
274
|
+
queryset,
|
|
275
|
+
fields=self.search_fields,
|
|
276
|
+
order_by_relevance=(not self.is_explicitly_ordered),
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
query = Q()
|
|
280
|
+
for field in self.search_fields or []:
|
|
281
|
+
query |= Q(**{field + "__icontains": self.search_query})
|
|
282
|
+
return queryset.filter(query)
|
|
283
|
+
|
|
205
284
|
@cached_property
|
|
206
285
|
def filters(self):
|
|
207
286
|
if self.filterset_class:
|
|
@@ -317,7 +396,7 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
317
396
|
ActiveFilter(
|
|
318
397
|
bound_field.auto_id,
|
|
319
398
|
filter_def.label,
|
|
320
|
-
"
|
|
399
|
+
f"{start_date_display} - {end_date_display}",
|
|
321
400
|
self.get_url_without_filter_param(
|
|
322
401
|
[
|
|
323
402
|
widget.suffixed(field_name, suffix)
|
|
@@ -405,8 +484,21 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
405
484
|
queryset = self.get_base_queryset()
|
|
406
485
|
queryset = self.order_queryset(queryset)
|
|
407
486
|
queryset = self.filter_queryset(queryset)
|
|
487
|
+
queryset = self.search_queryset(queryset)
|
|
408
488
|
return queryset
|
|
409
489
|
|
|
490
|
+
def paginate_queryset(self, queryset, page_size):
|
|
491
|
+
paginator = self.get_paginator(
|
|
492
|
+
queryset,
|
|
493
|
+
page_size,
|
|
494
|
+
orphans=self.get_paginate_orphans(),
|
|
495
|
+
allow_empty_first_page=self.get_allow_empty(),
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
page_number = self.request.GET.get(self.page_kwarg)
|
|
499
|
+
page = paginator.get_page(page_number)
|
|
500
|
+
return (paginator, page, page.object_list, page.has_other_pages())
|
|
501
|
+
|
|
410
502
|
def get_table_kwargs(self):
|
|
411
503
|
return {
|
|
412
504
|
"ordering": self.ordering,
|
|
@@ -437,6 +529,20 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
437
529
|
if self.index_results_url_name:
|
|
438
530
|
return reverse(self.index_results_url_name)
|
|
439
531
|
|
|
532
|
+
@cached_property
|
|
533
|
+
def no_results_message(self):
|
|
534
|
+
if not self.verbose_name_plural:
|
|
535
|
+
return _("There are no results.")
|
|
536
|
+
|
|
537
|
+
if self.is_searching or self.is_filtering:
|
|
538
|
+
return _("No %(model_name)s match your query.") % {
|
|
539
|
+
"model_name": self.verbose_name_plural
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return _("There are no %(model_name)s to display.") % {
|
|
543
|
+
"model_name": self.verbose_name_plural
|
|
544
|
+
}
|
|
545
|
+
|
|
440
546
|
def get_context_data(self, *args, **kwargs):
|
|
441
547
|
context = super().get_context_data(*args, **kwargs)
|
|
442
548
|
|
|
@@ -444,6 +550,9 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
444
550
|
|
|
445
551
|
context["index_url"] = self.index_url
|
|
446
552
|
context["index_results_url"] = self.index_results_url
|
|
553
|
+
context["verbose_name_plural"] = self.verbose_name_plural
|
|
554
|
+
context["no_results_message"] = self.no_results_message
|
|
555
|
+
context["ordering"] = self.ordering
|
|
447
556
|
context["table"] = table
|
|
448
557
|
context["media"] = table.media
|
|
449
558
|
# On Django's BaseListView, a listing where pagination is applied, but the results
|
|
@@ -462,6 +571,12 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
462
571
|
context["is_filtering"] = self.is_filtering
|
|
463
572
|
context["media"] += self.filters.form.media
|
|
464
573
|
|
|
574
|
+
if self.search_form:
|
|
575
|
+
context["search_form"] = self.search_form
|
|
576
|
+
context["is_searching"] = self.is_searching
|
|
577
|
+
context["query_string"] = self.search_query
|
|
578
|
+
context["media"] += self.search_form.media
|
|
579
|
+
|
|
465
580
|
# If we're rendering the results as an HTML fragment, the caller can pass a _w_filter_fragment=1
|
|
466
581
|
# URL parameter to indicate that the filters should be rendered as a <template> block so that
|
|
467
582
|
# we can replace the existing filters.
|
|
@@ -470,6 +585,8 @@ class BaseListingView(WagtailAdminTemplateMixin, BaseListView):
|
|
|
470
585
|
and self.filters
|
|
471
586
|
and self.results_only
|
|
472
587
|
)
|
|
588
|
+
# Ensure that the header buttons get re-rendered for the results-only view,
|
|
589
|
+
# in case they make use of the search/filter state
|
|
473
590
|
context["render_buttons_fragment"] = (
|
|
474
591
|
context.get("header_buttons") and self.results_only
|
|
475
592
|
)
|