wagtail 6.1.2__py3-none-any.whl → 6.2rc1__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 +15 -1
- wagtail/admin/checks.py +20 -30
- wagtail/admin/forms/pages.py +10 -0
- wagtail/admin/icons.py +43 -0
- wagtail/admin/locale/ar/LC_MESSAGES/django.po +2 -2
- wagtail/admin/locale/be/LC_MESSAGES/django.po +7 -7
- wagtail/admin/locale/be/LC_MESSAGES/djangojs.po +3 -3
- wagtail/admin/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ca/LC_MESSAGES/django.po +51 -50
- wagtail/admin/locale/cs/LC_MESSAGES/django.po +10 -8
- wagtail/admin/locale/de/LC_MESSAGES/django.po +49 -47
- wagtail/admin/locale/dv/LC_MESSAGES/django.po +8 -8
- wagtail/admin/locale/el/LC_MESSAGES/django.po +4 -4
- wagtail/admin/locale/en/LC_MESSAGES/django.po +405 -295
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +21 -3
- wagtail/admin/locale/es/LC_MESSAGES/django.po +40 -39
- wagtail/admin/locale/es_419/LC_MESSAGES/django.po +8 -8
- wagtail/admin/locale/et/LC_MESSAGES/django.po +14 -12
- wagtail/admin/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/fa/LC_MESSAGES/django.po +93 -19
- wagtail/admin/locale/fa/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/fa/LC_MESSAGES/djangojs.po +5 -1
- wagtail/admin/locale/fi/LC_MESSAGES/django.po +18 -18
- wagtail/admin/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/fr/LC_MESSAGES/django.po +134 -46
- wagtail/admin/locale/gl/LC_MESSAGES/django.po +55 -54
- wagtail/admin/locale/hr_HR/LC_MESSAGES/django.po +13 -12
- wagtail/admin/locale/hr_HR/LC_MESSAGES/djangojs.po +2 -2
- wagtail/admin/locale/hu/LC_MESSAGES/django.po +45 -42
- wagtail/admin/locale/id_ID/LC_MESSAGES/django.po +6 -6
- wagtail/admin/locale/is_IS/LC_MESSAGES/django.po +53 -51
- wagtail/admin/locale/it/LC_MESSAGES/django.po +56 -55
- wagtail/admin/locale/ja/LC_MESSAGES/django.po +2 -2
- wagtail/admin/locale/ko/LC_MESSAGES/django.po +18 -17
- wagtail/admin/locale/lt/LC_MESSAGES/django.po +4 -4
- wagtail/admin/locale/nb/LC_MESSAGES/django.po +22 -22
- wagtail/admin/locale/nl/LC_MESSAGES/django.po +44 -41
- wagtail/admin/locale/pl/LC_MESSAGES/django.po +49 -47
- wagtail/admin/locale/pl/LC_MESSAGES/djangojs.po +3 -3
- wagtail/admin/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/pt_BR/LC_MESSAGES/django.po +46 -26
- wagtail/admin/locale/pt_PT/LC_MESSAGES/django.po +21 -20
- wagtail/admin/locale/ro/LC_MESSAGES/django.po +51 -50
- wagtail/admin/locale/ru/LC_MESSAGES/django.po +60 -59
- wagtail/admin/locale/ru/LC_MESSAGES/djangojs.po +3 -3
- wagtail/admin/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sk_SK/LC_MESSAGES/django.po +15 -5
- wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/django.po +86 -39
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +2 -2
- wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/django.po +117 -41
- wagtail/admin/locale/sv/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/djangojs.po +5 -2
- wagtail/admin/locale/tet/LC_MESSAGES/django.po +2 -2
- wagtail/admin/locale/th/LC_MESSAGES/django.po +4 -4
- wagtail/admin/locale/tr/LC_MESSAGES/django.po +4 -4
- wagtail/admin/locale/tr_TR/LC_MESSAGES/django.po +4 -4
- wagtail/admin/locale/uk/LC_MESSAGES/django.po +11 -10
- wagtail/admin/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/zh_Hans/LC_MESSAGES/django.po +84 -13
- wagtail/admin/locale/zh_Hant/LC_MESSAGES/django.po +2 -2
- wagtail/admin/menu.py +2 -2
- wagtail/admin/migrations/0004_editingsession.py +57 -0
- wagtail/admin/migrations/0005_editingsession_is_editing.py +18 -0
- wagtail/admin/models.py +36 -3
- wagtail/admin/rich_text/editors/draftail/__init__.py +2 -20
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget.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/date-time-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/expanding-formset.js +1 -1
- wagtail/admin/static/wagtailadmin/js/filtered-select.js +1 -1
- wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/preview-panel.js +2 -1
- wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +11 -0
- wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js +2 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +11 -0
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +0 -12
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/templates/wagtailadmin/collection_privacy/ancestor_privacy.html +2 -6
- wagtail/admin/templates/wagtailadmin/generic/index_results.html +1 -17
- wagtail/admin/templates/wagtailadmin/generic/listing_results.html +20 -1
- wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +2 -11
- wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +2 -6
- wagtail/admin/templates/wagtailadmin/page_privacy/no_privacy.html +2 -0
- wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -1
- wagtail/admin/templates/wagtailadmin/reports/aging_pages_results.html +54 -0
- wagtail/admin/templates/wagtailadmin/reports/base_page_report.html +1 -17
- wagtail/admin/templates/wagtailadmin/reports/base_page_report_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/reports/base_report.html +1 -40
- wagtail/admin/templates/wagtailadmin/reports/base_report_results.html +1 -0
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +21 -27
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +48 -54
- wagtail/admin/templates/wagtailadmin/reports/{locked_pages.html → locked_pages_results.html} +3 -3
- wagtail/admin/templates/wagtailadmin/reports/page_types_usage_results.html +10 -0
- wagtail/admin/templates/wagtailadmin/reports/site_history_results.html +53 -0
- wagtail/admin/templates/wagtailadmin/reports/workflow_results.html +74 -0
- wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +56 -0
- wagtail/admin/templates/wagtailadmin/shared/_workflow_init.html +8 -44
- wagtail/admin/templates/wagtailadmin/shared/avatar.html +11 -1
- wagtail/admin/templates/wagtailadmin/shared/dialog/dialog.html +5 -4
- wagtail/admin/templates/wagtailadmin/shared/dropdown/dropdown_button.html +2 -1
- wagtail/admin/templates/wagtailadmin/shared/editing_sessions/list.html +132 -0
- wagtail/admin/templates/wagtailadmin/shared/editing_sessions/module.html +44 -0
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +7 -1
- wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/checks.html +32 -16
- wagtail/admin/templates/wagtailadmin/skeleton.html +1 -1
- wagtail/admin/templates/wagtailadmin/userbar/item_accessibility.html +9 -11
- wagtail/admin/templatetags/wagtailadmin_tags.py +13 -2
- wagtail/admin/tests/formats/en/__init__.py +0 -0
- wagtail/admin/tests/formats/en/formats.py +1 -0
- wagtail/admin/tests/pages/test_create_page.py +47 -0
- wagtail/admin/tests/pages/test_edit_page.py +10 -8
- wagtail/admin/tests/pages/test_parent_page_chooser_view.py +45 -1
- wagtail/admin/tests/test_checks.py +53 -3
- wagtail/admin/tests/test_collections_views.py +62 -1
- wagtail/admin/tests/test_edit_handlers.py +37 -0
- wagtail/admin/tests/test_editing_sessions.py +1336 -0
- wagtail/admin/tests/test_icon_sprite.py +12 -21
- wagtail/admin/tests/test_page_chooser.py +309 -7
- wagtail/admin/tests/test_privacy.py +82 -0
- wagtail/admin/tests/test_reports_views.py +464 -70
- wagtail/admin/tests/test_userbar.py +93 -6
- wagtail/admin/tests/test_workflows.py +223 -33
- wagtail/admin/tests/viewsets/test_model_viewset.py +151 -2
- wagtail/admin/ui/editing_sessions.py +57 -0
- wagtail/admin/urls/__init__.py +9 -15
- wagtail/admin/urls/editing_sessions.py +17 -0
- wagtail/admin/urls/reports.py +33 -1
- wagtail/admin/userbar.py +77 -20
- wagtail/admin/views/chooser.py +49 -22
- wagtail/admin/views/collections.py +0 -11
- wagtail/admin/views/editing_sessions.py +193 -0
- wagtail/admin/views/generic/__init__.py +1 -0
- wagtail/admin/views/generic/base.py +3 -2
- wagtail/admin/views/generic/history.py +9 -3
- wagtail/admin/views/generic/mixins.py +44 -3
- wagtail/admin/views/generic/models.py +46 -72
- wagtail/admin/views/generic/permissions.py +20 -10
- wagtail/admin/views/home.py +2 -31
- wagtail/admin/views/page_privacy.py +20 -5
- wagtail/admin/views/pages/choose_parent.py +62 -0
- wagtail/admin/views/pages/edit.py +28 -0
- wagtail/admin/views/reports/aging_pages.py +6 -10
- wagtail/admin/views/reports/audit_logging.py +13 -42
- wagtail/admin/views/reports/base.py +31 -4
- wagtail/admin/views/reports/locked_pages.py +5 -8
- wagtail/admin/views/reports/page_types_usage.py +6 -10
- wagtail/admin/views/reports/workflows.py +36 -12
- wagtail/admin/viewsets/base.py +8 -3
- wagtail/admin/viewsets/chooser.py +1 -1
- wagtail/admin/viewsets/model.py +26 -1
- wagtail/admin/wagtail_hooks.py +2 -1
- wagtail/api/v2/filters.py +6 -0
- wagtail/api/v2/tests/test_documents.py +1 -1
- wagtail/api/v2/tests/test_images.py +1 -1
- wagtail/api/v2/tests/test_pages.py +11 -1
- wagtail/api/v2/utils.py +2 -2
- wagtail/blocks/base.py +35 -12
- wagtail/blocks/definition_lookup.py +85 -0
- wagtail/blocks/list_block.py +12 -0
- wagtail/blocks/migrations/migrate_operation.py +2 -0
- wagtail/blocks/stream_block.py +19 -0
- wagtail/blocks/struct_block.py +19 -0
- wagtail/contrib/forms/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/forms/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/forms/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/forms/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/pt_BR/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/forms/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/forms/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/frontend_cache/backends/__init__.py +5 -0
- wagtail/contrib/frontend_cache/backends/azure.py +179 -0
- wagtail/contrib/frontend_cache/backends/base.py +28 -0
- wagtail/contrib/frontend_cache/backends/cloudflare.py +114 -0
- wagtail/contrib/frontend_cache/backends/cloudfront.py +99 -0
- wagtail/contrib/frontend_cache/backends/http.py +64 -0
- wagtail/contrib/frontend_cache/tests.py +59 -17
- wagtail/contrib/frontend_cache/utils.py +26 -8
- wagtail/contrib/redirects/filters.py +15 -1
- wagtail/contrib/redirects/locale/ar/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/redirects/locale/bg/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/cs/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/redirects/locale/de/LC_MESSAGES/django.po +5 -4
- wagtail/contrib/redirects/locale/el/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +37 -72
- wagtail/contrib/redirects/locale/es/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/redirects/locale/et/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/fa/LC_MESSAGES/django.po +18 -5
- wagtail/contrib/redirects/locale/fi/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/redirects/locale/fr/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/gl/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/hr_HR/LC_MESSAGES/django.po +8 -8
- wagtail/contrib/redirects/locale/hu/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/redirects/locale/id_ID/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/is_IS/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/ja/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/redirects/locale/ko/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/lt/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/mn/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/nb/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/nl/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/pl/LC_MESSAGES/django.po +9 -9
- wagtail/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.po +5 -5
- wagtail/contrib/redirects/locale/pt_PT/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/ro/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/ru/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/redirects/locale/sk_SK/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/sl/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/redirects/locale/sr/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/tet/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/th/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/tr/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/tr_TR/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/uk/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/zh/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/models.py +6 -5
- wagtail/contrib/redirects/templates/wagtailredirects/edit.html +1 -38
- wagtail/contrib/redirects/tests/test_redirects.py +141 -1
- wagtail/contrib/redirects/urls.py +1 -2
- wagtail/contrib/redirects/views.py +39 -80
- wagtail/contrib/routable_page/models.py +6 -4
- wagtail/contrib/routable_page/tests.py +11 -0
- wagtail/contrib/search_promotions/locale/ar/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/be/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/search_promotions/locale/ca/LC_MESSAGES/django.po +8 -8
- wagtail/contrib/search_promotions/locale/cs/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/de/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/el/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/search_promotions/locale/es/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/et/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/fa/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/fi/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/fr/LC_MESSAGES/django.po +9 -6
- wagtail/contrib/search_promotions/locale/gl/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/hr_HR/LC_MESSAGES/django.po +8 -8
- wagtail/contrib/search_promotions/locale/hu/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/id_ID/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/is_IS/LC_MESSAGES/django.po +8 -8
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/ja/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/ko/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/lt/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/nb/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/nl/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/pl/LC_MESSAGES/django.po +9 -9
- wagtail/contrib/search_promotions/locale/pt_BR/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/pt_PT/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/ro/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/ru/LC_MESSAGES/django.po +9 -9
- wagtail/contrib/search_promotions/locale/sk_SK/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/sl/LC_MESSAGES/django.po +62 -8
- wagtail/contrib/search_promotions/locale/sr/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/search_promotions/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/sv/LC_MESSAGES/django.po +9 -6
- wagtail/contrib/search_promotions/locale/th/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/tr/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/tr_TR/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/uk/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/search_promotions/locale/zh_Hans/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/search_promotions/locale/zh_Hant/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/settings/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/settings/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/settings/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/settings/locale/pt_BR/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/settings/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/settings/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/sk_SK/LC_MESSAGES/django.po +10 -1
- wagtail/contrib/settings/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/settings/locale/sr/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/simple_translation/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/simple_translation/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/simple_translation/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/simple_translation/locale/pt_BR/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/simple_translation/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/simple_translation/models.py +2 -1
- wagtail/contrib/styleguide/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/styleguide/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/styleguide/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/styleguide/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/styleguide/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/styleguide/locale/sk_SK/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/styleguide/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/styleguide/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/styleguide/locale/zh_Hans/LC_MESSAGES/django.po +3 -0
- wagtail/contrib/table_block/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/fr/LC_MESSAGES/django.po +27 -1
- wagtail/contrib/table_block/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/table_block/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/table_block/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/table_block/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/sl/LC_MESSAGES/django.po +29 -3
- wagtail/contrib/table_block/static/table_block/js/table.js +1 -1
- wagtail/contrib/typed_table_block/blocks.py +19 -0
- wagtail/contrib/typed_table_block/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/contrib/typed_table_block/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/fr/LC_MESSAGES/django.po +12 -1
- wagtail/contrib/typed_table_block/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/typed_table_block/locale/pt_BR/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/typed_table_block/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/sl/LC_MESSAGES/django.po +14 -4
- wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
- wagtail/contrib/typed_table_block/tests.py +38 -0
- wagtail/coreutils.py +1 -1
- wagtail/documents/__init__.py +1 -1
- wagtail/documents/locale/ar/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/be/LC_MESSAGES/django.po +11 -11
- wagtail/documents/locale/bg/LC_MESSAGES/django.po +4 -4
- wagtail/documents/locale/ca/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/ca/LC_MESSAGES/django.po +12 -11
- wagtail/documents/locale/cs/LC_MESSAGES/django.po +6 -6
- wagtail/documents/locale/de/LC_MESSAGES/django.po +10 -8
- wagtail/documents/locale/el/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/en/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/es/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/et/LC_MESSAGES/django.po +6 -6
- wagtail/documents/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/fa/LC_MESSAGES/django.po +17 -8
- wagtail/documents/locale/fi/LC_MESSAGES/django.po +10 -10
- wagtail/documents/locale/fr/LC_MESSAGES/django.po +6 -6
- wagtail/documents/locale/gl/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/hr_HR/LC_MESSAGES/django.po +14 -14
- wagtail/documents/locale/hu/LC_MESSAGES/django.po +12 -12
- wagtail/documents/locale/id_ID/LC_MESSAGES/django.po +6 -6
- wagtail/documents/locale/is_IS/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/it/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/ja/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/ko/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/lt/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/mi/LC_MESSAGES/django.po +10 -10
- wagtail/documents/locale/mn/LC_MESSAGES/django.po +5 -4
- wagtail/documents/locale/nb/LC_MESSAGES/django.po +6 -6
- wagtail/documents/locale/nl/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/pl/LC_MESSAGES/django.po +11 -11
- wagtail/documents/locale/pt_BR/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/pt_PT/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/ro/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/ru/LC_MESSAGES/django.po +9 -9
- wagtail/documents/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/sk_SK/LC_MESSAGES/django.po +55 -12
- wagtail/documents/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/sl/LC_MESSAGES/django.po +30 -10
- wagtail/documents/locale/sr/LC_MESSAGES/django.po +2 -2
- wagtail/documents/locale/sv/LC_MESSAGES/django.po +6 -6
- wagtail/documents/locale/th/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/tr/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/tr_TR/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/uk/LC_MESSAGES/django.po +8 -8
- wagtail/documents/locale/zh/LC_MESSAGES/django.po +2 -2
- wagtail/documents/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/zh_Hans/LC_MESSAGES/django.po +11 -5
- wagtail/documents/locale/zh_Hant/LC_MESSAGES/django.po +4 -4
- wagtail/documents/models.py +5 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser-modal.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser-telepath.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser.js +1 -1
- wagtail/documents/tests/test_models.py +5 -1
- wagtail/embeds/apps.py +2 -0
- wagtail/embeds/embeds.py +12 -14
- wagtail/embeds/finders/__init__.py +2 -0
- wagtail/embeds/finders/facebook.py +17 -33
- wagtail/embeds/finders/instagram.py +19 -16
- wagtail/embeds/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/embeds/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/embeds/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/embeds/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/embeds/signal_handlers.py +13 -0
- wagtail/embeds/tests/test_embeds.py +7 -7
- wagtail/fields.py +58 -14
- wagtail/images/__init__.py +1 -1
- wagtail/images/locale/ar/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/images/locale/ca/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/cs/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/cy/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/de/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/el/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/en/LC_MESSAGES/django.po +34 -34
- wagtail/images/locale/es/LC_MESSAGES/django.po +10 -10
- wagtail/images/locale/et/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/fa/LC_MESSAGES/django.po +28 -9
- wagtail/images/locale/fi/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/fr/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/gl/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/hr_HR/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/hu/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/id_ID/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/is_IS/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/it/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/ja/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/ko/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/lt/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/nb/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/nl/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/pl/LC_MESSAGES/django.po +11 -11
- wagtail/images/locale/pt_BR/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/pt_PT/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/ro/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/ru/LC_MESSAGES/django.po +11 -11
- wagtail/images/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/sk_SK/LC_MESSAGES/django.po +23 -8
- wagtail/images/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/sl/LC_MESSAGES/django.po +44 -12
- wagtail/images/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/sv/LC_MESSAGES/django.po +20 -8
- wagtail/images/locale/tet/LC_MESSAGES/django.po +4 -4
- wagtail/images/locale/th/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/tr/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/tr_TR/LC_MESSAGES/django.po +6 -6
- wagtail/images/locale/uk/LC_MESSAGES/django.po +8 -8
- wagtail/images/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/zh_Hans/LC_MESSAGES/django.po +49 -5
- wagtail/images/locale/zh_Hant/LC_MESSAGES/django.po +4 -4
- wagtail/images/models.py +3 -0
- wagtail/images/static/wagtailimages/js/image-chooser-modal.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
- wagtail/images/templates/wagtailimages/images/edit.html +4 -4
- wagtail/images/tests/test_admin_views.py +58 -2
- wagtail/images/tests/test_image_operations.py +12 -0
- wagtail/images/tests/tests.py +27 -2
- wagtail/images/views/chooser.py +6 -1
- wagtail/images/views/images.py +7 -3
- wagtail/images/views/serve.py +1 -0
- wagtail/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/locale/en/LC_MESSAGES/django.po +84 -80
- wagtail/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/fa/LC_MESSAGES/django.po +3 -0
- wagtail/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/fr/LC_MESSAGES/django.po +23 -4
- wagtail/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/locale/pt_BR/LC_MESSAGES/django.po +1 -1
- wagtail/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sv/LC_MESSAGES/django.po +11 -2
- wagtail/locales/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/locales/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/locales/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/locales/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/locales/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/locales/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/locales/tests.py +16 -0
- wagtail/locales/wagtail_hooks.py +0 -9
- wagtail/migrations/0094_alter_page_locale.py +19 -0
- wagtail/models/__init__.py +11 -5
- wagtail/models/i18n.py +6 -1
- wagtail/project_template/requirements.txt +1 -1
- wagtail/search/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/search/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/search/locale/fa/LC_MESSAGES/django.po +24 -0
- wagtail/search/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/search/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/search/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- wagtail/search/locale/pt_BR/LC_MESSAGES/django.po +2 -2
- wagtail/search/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/search/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/search/tests/test_queries.py +24 -0
- wagtail/search/utils.py +6 -12
- wagtail/signals.py +4 -0
- wagtail/sites/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/sites/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/sites/locale/hr_HR/LC_MESSAGES/django.po +2 -2
- wagtail/sites/locale/pl/LC_MESSAGES/django.po +3 -3
- wagtail/sites/locale/ru/LC_MESSAGES/django.po +3 -3
- wagtail/sites/locale/sl/LC_MESSAGES/django.po +2 -2
- wagtail/sites/locale/sr/LC_MESSAGES/django.po +2 -2
- wagtail/sites/tests.py +15 -0
- wagtail/sites/wagtail_hooks.py +0 -9
- wagtail/snippets/locale/be/LC_MESSAGES/django.po +3 -3
- wagtail/snippets/locale/ca/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/de/LC_MESSAGES/django.po +5 -5
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +9 -9
- wagtail/snippets/locale/es/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/fa/LC_MESSAGES/django.po +17 -1
- wagtail/snippets/locale/fr/LC_MESSAGES/django.po +5 -5
- wagtail/snippets/locale/gl/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/hr_HR/LC_MESSAGES/django.po +8 -8
- wagtail/snippets/locale/hu/LC_MESSAGES/django.po +7 -7
- wagtail/snippets/locale/is_IS/LC_MESSAGES/django.po +5 -5
- wagtail/snippets/locale/it/LC_MESSAGES/django.po +5 -5
- wagtail/snippets/locale/ko/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/nb/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/nl/LC_MESSAGES/django.po +8 -8
- wagtail/snippets/locale/pl/LC_MESSAGES/django.po +9 -9
- wagtail/snippets/locale/pt_BR/LC_MESSAGES/django.po +1 -1
- wagtail/snippets/locale/ro/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/ru/LC_MESSAGES/django.po +8 -8
- wagtail/snippets/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/sk_SK/LC_MESSAGES/django.po +3 -0
- wagtail/snippets/locale/sl/LC_MESSAGES/django.po +8 -8
- wagtail/snippets/locale/sr/LC_MESSAGES/django.po +2 -2
- wagtail/snippets/locale/sv/LC_MESSAGES/django.po +6 -6
- wagtail/snippets/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/zh_Hans/LC_MESSAGES/django.po +40 -1
- wagtail/snippets/permissions.py +5 -3
- 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/snippets/action_menu/menu.html +1 -1
- wagtail/snippets/tests/test_snippets.py +78 -12
- wagtail/snippets/tests/test_viewset.py +22 -0
- wagtail/snippets/views/snippets.py +19 -14
- wagtail/snippets/wagtail_hooks.py +2 -10
- wagtail/templatetags/wagtailcore_tags.py +3 -0
- wagtail/test/dummy_external_storage.py +1 -1
- wagtail/test/i18n/migrations/0003_alter_clusterabletestmodel_locale_and_more.py +40 -0
- wagtail/test/routablepage/models.py +4 -0
- wagtail/test/snippets/migrations/0012_alter_translatablesnippet_locale.py +20 -0
- wagtail/test/testapp/migrations/0038_sociallink.py +52 -0
- wagtail/test/testapp/migrations/0039_alter_eventcategory_locale_and_more.py +45 -0
- wagtail/test/testapp/models.py +24 -0
- wagtail/test/testapp/views.py +1 -0
- wagtail/test/testapp/wagtail_hooks.py +9 -0
- wagtail/test/urls_multilang.py +6 -1
- wagtail/test/urls_multilang_non_root.py +11 -0
- wagtail/tests/streamfield_migrations/test_migrations.py +53 -12
- wagtail/tests/test_audit_log.py +72 -2
- wagtail/tests/test_blocks.py +103 -0
- wagtail/tests/test_signals.py +49 -2
- wagtail/tests/test_streamfield.py +153 -0
- wagtail/tests/test_utils.py +42 -1
- wagtail/tests/tests.py +5 -0
- wagtail/users/apps.py +1 -0
- wagtail/users/forms.py +7 -0
- wagtail/users/locale/ar/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/be/LC_MESSAGES/django.po +9 -9
- wagtail/users/locale/ca/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/cs/LC_MESSAGES/django.po +6 -6
- wagtail/users/locale/cy/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/de/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/el/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/en/LC_MESSAGES/django.po +55 -50
- wagtail/users/locale/es/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/et/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/fa/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/fa/LC_MESSAGES/django.po +69 -7
- wagtail/users/locale/fi/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/fr/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/fr/LC_MESSAGES/django.po +52 -11
- wagtail/users/locale/gl/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/hr_HR/LC_MESSAGES/django.po +10 -10
- wagtail/users/locale/hu/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/id_ID/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/is_IS/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/it/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/ja/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/ko/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/lt/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/lv/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/mn/LC_MESSAGES/django.po +5 -4
- wagtail/users/locale/nb/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/nl/LC_MESSAGES/django.po +6 -6
- wagtail/users/locale/pl/LC_MESSAGES/django.po +9 -9
- wagtail/users/locale/pt_BR/LC_MESSAGES/django.po +9 -9
- wagtail/users/locale/pt_PT/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/ro/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/ru/LC_MESSAGES/django.po +11 -11
- wagtail/users/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sk_SK/LC_MESSAGES/django.po +12 -5
- wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sl/LC_MESSAGES/django.po +56 -12
- wagtail/users/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sv/LC_MESSAGES/django.po +49 -10
- wagtail/users/locale/tet/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/th/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/tr/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/tr_TR/LC_MESSAGES/django.po +4 -4
- wagtail/users/locale/uk/LC_MESSAGES/django.po +8 -8
- wagtail/users/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/zh_Hans/LC_MESSAGES/django.po +49 -5
- wagtail/users/locale/zh_Hant/LC_MESSAGES/django.po +2 -2
- wagtail/users/models.py +1 -0
- wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +3 -2
- wagtail/users/templatetags/wagtailusers_tags.py +9 -0
- wagtail/users/tests/__init__.py +7 -1
- wagtail/users/tests/test_admin_views.py +117 -32
- wagtail/users/views/groups.py +4 -0
- wagtail/users/views/users.py +58 -14
- wagtail/users/wagtail_hooks.py +7 -123
- wagtail/utils/utils.py +27 -0
- wagtail/utils/version.py +5 -2
- wagtail-6.2rc1.dist-info/METADATA +78 -0
- {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/RECORD +634 -607
- {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/WHEEL +1 -1
- wagtail/admin/templates/wagtailadmin/reports/aging_pages.html +0 -58
- wagtail/admin/templates/wagtailadmin/reports/page_types_usage.html +0 -18
- wagtail/admin/templates/wagtailadmin/reports/site_history.html +0 -57
- wagtail/admin/templates/wagtailadmin/reports/workflow.html +0 -81
- wagtail/admin/templates/wagtailadmin/reports/workflow_tasks.html +0 -63
- wagtail/contrib/frontend_cache/backends.py +0 -400
- wagtail/contrib/redirects/templates/wagtailredirects/list.html +0 -43
- wagtail/contrib/redirects/templates/wagtailredirects/reports/redirects_report.html +0 -14
- wagtail/contrib/redirects/tests/test_reports_view.py +0 -82
- wagtail-6.1.2.dist-info/METADATA +0 -78
- {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/LICENSE +0 -0
- {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
5
|
+
|
|
6
|
+
from .base import BaseBackend
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger("wagtail.frontendcache")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
__all__ = ["CloudflareBackend"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CloudflareBackend(BaseBackend):
|
|
15
|
+
CHUNK_SIZE = 30
|
|
16
|
+
|
|
17
|
+
def __init__(self, params):
|
|
18
|
+
super().__init__(params)
|
|
19
|
+
|
|
20
|
+
self.cloudflare_email = params.pop("EMAIL", None)
|
|
21
|
+
self.cloudflare_api_key = params.pop("TOKEN", None) or params.pop(
|
|
22
|
+
"API_KEY", None
|
|
23
|
+
)
|
|
24
|
+
self.cloudflare_token = params.pop("BEARER_TOKEN", None)
|
|
25
|
+
self.cloudflare_zoneid = params.pop("ZONEID")
|
|
26
|
+
self.cloudflare_purge_endpoint_url = (
|
|
27
|
+
"https://api.cloudflare.com/client/v4/zones/{}/purge_cache".format(
|
|
28
|
+
self.cloudflare_zoneid
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
(not self.cloudflare_email and self.cloudflare_api_key)
|
|
34
|
+
or (self.cloudflare_email and not self.cloudflare_api_key)
|
|
35
|
+
or (
|
|
36
|
+
not any(
|
|
37
|
+
[
|
|
38
|
+
self.cloudflare_email,
|
|
39
|
+
self.cloudflare_api_key,
|
|
40
|
+
self.cloudflare_token,
|
|
41
|
+
]
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
):
|
|
45
|
+
raise ImproperlyConfigured(
|
|
46
|
+
"The setting 'WAGTAILFRONTENDCACHE' requires both 'EMAIL' and 'API_KEY', or 'BEARER_TOKEN' to be specified."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def _purge_urls(self, urls):
|
|
50
|
+
try:
|
|
51
|
+
purge_url = (
|
|
52
|
+
"https://api.cloudflare.com/client/v4/zones/{}/purge_cache".format(
|
|
53
|
+
self.cloudflare_zoneid
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
headers = {"Content-Type": "application/json"}
|
|
58
|
+
|
|
59
|
+
if self.cloudflare_token:
|
|
60
|
+
headers["Authorization"] = f"Bearer {self.cloudflare_token}"
|
|
61
|
+
else:
|
|
62
|
+
headers["X-Auth-Email"] = self.cloudflare_email
|
|
63
|
+
headers["X-Auth-Key"] = self.cloudflare_api_key
|
|
64
|
+
|
|
65
|
+
data = {"files": urls}
|
|
66
|
+
|
|
67
|
+
response = requests.delete(
|
|
68
|
+
purge_url,
|
|
69
|
+
json=data,
|
|
70
|
+
headers=headers,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
response_json = response.json()
|
|
75
|
+
except ValueError:
|
|
76
|
+
if response.status_code != 200:
|
|
77
|
+
response.raise_for_status()
|
|
78
|
+
else:
|
|
79
|
+
for url in urls:
|
|
80
|
+
logger.error(
|
|
81
|
+
"Couldn't purge '%s' from Cloudflare. Unexpected JSON parse error.",
|
|
82
|
+
url,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
except requests.exceptions.HTTPError as e:
|
|
86
|
+
for url in urls:
|
|
87
|
+
logging.exception(
|
|
88
|
+
"Couldn't purge '%s' from Cloudflare. HTTPError: %d",
|
|
89
|
+
url,
|
|
90
|
+
e.response.status_code,
|
|
91
|
+
)
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
if response_json["success"] is False:
|
|
95
|
+
error_messages = ", ".join(
|
|
96
|
+
[str(err["message"]) for err in response_json["errors"]]
|
|
97
|
+
)
|
|
98
|
+
for url in urls:
|
|
99
|
+
logger.error(
|
|
100
|
+
"Couldn't purge '%s' from Cloudflare. Cloudflare errors '%s'",
|
|
101
|
+
url,
|
|
102
|
+
error_messages,
|
|
103
|
+
)
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
def purge_batch(self, urls):
|
|
107
|
+
# Break the batched URLs in to chunks to fit within Cloudflare's maximum size for
|
|
108
|
+
# the purge_cache call (https://api.cloudflare.com/#zone-purge-files-by-url)
|
|
109
|
+
for i in range(0, len(urls), self.CHUNK_SIZE):
|
|
110
|
+
chunk = urls[i : i + self.CHUNK_SIZE]
|
|
111
|
+
self._purge_urls(chunk)
|
|
112
|
+
|
|
113
|
+
def purge(self, url):
|
|
114
|
+
self._purge_urls([url])
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import uuid
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
from warnings import warn
|
|
6
|
+
|
|
7
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
8
|
+
|
|
9
|
+
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
10
|
+
|
|
11
|
+
from .base import BaseBackend
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger("wagtail.frontendcache")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["CloudfrontBackend"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class CloudfrontBackend(BaseBackend):
|
|
20
|
+
def __init__(self, params):
|
|
21
|
+
import boto3
|
|
22
|
+
|
|
23
|
+
super().__init__(params)
|
|
24
|
+
|
|
25
|
+
self.client = boto3.client(
|
|
26
|
+
"cloudfront",
|
|
27
|
+
aws_access_key_id=params.get("AWS_ACCESS_KEY_ID"),
|
|
28
|
+
aws_secret_access_key=params.get("AWS_SECRET_ACCESS_KEY"),
|
|
29
|
+
aws_session_token=params.get("AWS_SESSION_TOKEN"),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
self.cloudfront_distribution_id = params.pop("DISTRIBUTION_ID")
|
|
34
|
+
except KeyError:
|
|
35
|
+
raise ImproperlyConfigured(
|
|
36
|
+
"The setting 'WAGTAILFRONTENDCACHE' requires the object 'DISTRIBUTION_ID'."
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Add known hostnames for hostname validation (if not already defined)
|
|
40
|
+
# RemovedInWagtail70Warning
|
|
41
|
+
if isinstance(self.cloudfront_distribution_id, dict):
|
|
42
|
+
if "HOSTNAMES" in params:
|
|
43
|
+
self.hostnames.extend(self.cloudfront_distribution_id.keys())
|
|
44
|
+
else:
|
|
45
|
+
self.hostnames = list(self.cloudfront_distribution_id.keys())
|
|
46
|
+
|
|
47
|
+
def purge_batch(self, urls):
|
|
48
|
+
paths_by_distribution_id = defaultdict(list)
|
|
49
|
+
|
|
50
|
+
for url in urls:
|
|
51
|
+
url_parsed = urlparse(url)
|
|
52
|
+
distribution_id = None
|
|
53
|
+
|
|
54
|
+
if isinstance(self.cloudfront_distribution_id, dict):
|
|
55
|
+
warn(
|
|
56
|
+
"Using a `DISTRIBUTION_ID` mapping is deprecated - use `HOSTNAMES` in combination with multiple backends instead.",
|
|
57
|
+
category=RemovedInWagtail70Warning,
|
|
58
|
+
)
|
|
59
|
+
host = url_parsed.hostname
|
|
60
|
+
if host in self.cloudfront_distribution_id:
|
|
61
|
+
distribution_id = self.cloudfront_distribution_id.get(host)
|
|
62
|
+
else:
|
|
63
|
+
logger.warning(
|
|
64
|
+
"Couldn't purge '%s' from CloudFront. Hostname '%s' not found in the DISTRIBUTION_ID mapping",
|
|
65
|
+
url,
|
|
66
|
+
host,
|
|
67
|
+
)
|
|
68
|
+
else:
|
|
69
|
+
distribution_id = self.cloudfront_distribution_id
|
|
70
|
+
|
|
71
|
+
if distribution_id:
|
|
72
|
+
paths_by_distribution_id[distribution_id].append(url_parsed.path)
|
|
73
|
+
|
|
74
|
+
for distribution_id, paths in paths_by_distribution_id.items():
|
|
75
|
+
self._create_invalidation(distribution_id, paths)
|
|
76
|
+
|
|
77
|
+
def purge(self, url):
|
|
78
|
+
self.purge_batch([url])
|
|
79
|
+
|
|
80
|
+
def _create_invalidation(self, distribution_id, paths):
|
|
81
|
+
import botocore
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
self.client.create_invalidation(
|
|
85
|
+
DistributionId=distribution_id,
|
|
86
|
+
InvalidationBatch={
|
|
87
|
+
"Paths": {"Quantity": len(paths), "Items": paths},
|
|
88
|
+
"CallerReference": str(uuid.uuid4()),
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
except botocore.exceptions.ClientError as e:
|
|
92
|
+
for path in paths:
|
|
93
|
+
logger.error(
|
|
94
|
+
"Couldn't purge path '%s' from CloudFront (DistributionId=%s). ClientError: %s %s",
|
|
95
|
+
path,
|
|
96
|
+
distribution_id,
|
|
97
|
+
e.response["Error"]["Code"],
|
|
98
|
+
e.response["Error"]["Message"],
|
|
99
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from urllib.error import HTTPError, URLError
|
|
3
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
4
|
+
from urllib.request import Request, urlopen
|
|
5
|
+
|
|
6
|
+
from wagtail import __version__
|
|
7
|
+
|
|
8
|
+
from .base import BaseBackend
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger("wagtail.frontendcache")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
__all__ = ["PurgeRequest", "HTTPBackend"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class PurgeRequest(Request):
|
|
17
|
+
def get_method(self):
|
|
18
|
+
return "PURGE"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class HTTPBackend(BaseBackend):
|
|
22
|
+
def __init__(self, params):
|
|
23
|
+
super().__init__(params)
|
|
24
|
+
location_url_parsed = urlsplit(params.pop("LOCATION"))
|
|
25
|
+
self.cache_scheme = location_url_parsed.scheme
|
|
26
|
+
self.cache_netloc = location_url_parsed.netloc
|
|
27
|
+
|
|
28
|
+
def purge(self, url):
|
|
29
|
+
url_parsed = urlsplit(url)
|
|
30
|
+
host = url_parsed.hostname
|
|
31
|
+
|
|
32
|
+
# Append port to host if it is set in the original URL
|
|
33
|
+
if url_parsed.port:
|
|
34
|
+
host += ":" + str(url_parsed.port)
|
|
35
|
+
|
|
36
|
+
request = PurgeRequest(
|
|
37
|
+
url=urlunsplit(
|
|
38
|
+
[
|
|
39
|
+
self.cache_scheme,
|
|
40
|
+
self.cache_netloc,
|
|
41
|
+
url_parsed.path,
|
|
42
|
+
url_parsed.query,
|
|
43
|
+
url_parsed.fragment,
|
|
44
|
+
]
|
|
45
|
+
),
|
|
46
|
+
headers={
|
|
47
|
+
"Host": host,
|
|
48
|
+
"User-Agent": "Wagtail-frontendcache/" + __version__,
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
urlopen(request)
|
|
54
|
+
except HTTPError as e:
|
|
55
|
+
logger.error(
|
|
56
|
+
"Couldn't purge '%s' from HTTP cache. HTTPError: %d %s",
|
|
57
|
+
url,
|
|
58
|
+
e.code,
|
|
59
|
+
e.reason,
|
|
60
|
+
)
|
|
61
|
+
except URLError as e:
|
|
62
|
+
logger.error(
|
|
63
|
+
"Couldn't purge '%s' from HTTP cache. URLError: %s", url, e.reason
|
|
64
|
+
)
|
|
@@ -5,7 +5,7 @@ import requests
|
|
|
5
5
|
from azure.mgmt.cdn import CdnManagementClient
|
|
6
6
|
from azure.mgmt.frontdoor import FrontDoorManagementClient
|
|
7
7
|
from django.core.exceptions import ImproperlyConfigured
|
|
8
|
-
from django.test import TestCase
|
|
8
|
+
from django.test import SimpleTestCase, TestCase
|
|
9
9
|
from django.test.utils import override_settings
|
|
10
10
|
|
|
11
11
|
from wagtail.contrib.frontend_cache.backends import (
|
|
@@ -19,6 +19,7 @@ from wagtail.contrib.frontend_cache.backends import (
|
|
|
19
19
|
from wagtail.contrib.frontend_cache.utils import get_backends
|
|
20
20
|
from wagtail.models import Page
|
|
21
21
|
from wagtail.test.testapp.models import EventIndex
|
|
22
|
+
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
|
22
23
|
|
|
23
24
|
from .utils import (
|
|
24
25
|
PurgeBatch,
|
|
@@ -29,7 +30,7 @@ from .utils import (
|
|
|
29
30
|
)
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
class TestBackendConfiguration(
|
|
33
|
+
class TestBackendConfiguration(SimpleTestCase):
|
|
33
34
|
def test_default(self):
|
|
34
35
|
backends = get_backends()
|
|
35
36
|
|
|
@@ -81,6 +82,8 @@ class TestBackendConfiguration(TestCase):
|
|
|
81
82
|
"cloudfront": {
|
|
82
83
|
"BACKEND": "wagtail.contrib.frontend_cache.backends.CloudfrontBackend",
|
|
83
84
|
"DISTRIBUTION_ID": "frontend",
|
|
85
|
+
"AWS_ACCESS_KEY_ID": "my-access-key-id",
|
|
86
|
+
"AWS_SECRET_ACCESS_KEY": "my-secret-access-key",
|
|
84
87
|
},
|
|
85
88
|
}
|
|
86
89
|
)
|
|
@@ -90,6 +93,12 @@ class TestBackendConfiguration(TestCase):
|
|
|
90
93
|
|
|
91
94
|
self.assertEqual(backends["cloudfront"].cloudfront_distribution_id, "frontend")
|
|
92
95
|
|
|
96
|
+
credentials = backends["cloudfront"].client._request_signer._credentials
|
|
97
|
+
|
|
98
|
+
self.assertEqual(credentials.method, "explicit")
|
|
99
|
+
self.assertEqual(credentials.access_key, "my-access-key-id")
|
|
100
|
+
self.assertEqual(credentials.secret_key, "my-secret-access-key")
|
|
101
|
+
|
|
93
102
|
def test_azure_cdn(self):
|
|
94
103
|
backends = get_backends(
|
|
95
104
|
backend_settings={
|
|
@@ -172,7 +181,7 @@ class TestBackendConfiguration(TestCase):
|
|
|
172
181
|
self.assertIs(client._config.credential, mock_credentials)
|
|
173
182
|
|
|
174
183
|
@mock.patch(
|
|
175
|
-
"wagtail.contrib.frontend_cache.backends.AzureCdnBackend._make_purge_call"
|
|
184
|
+
"wagtail.contrib.frontend_cache.backends.azure.AzureCdnBackend._make_purge_call"
|
|
176
185
|
)
|
|
177
186
|
def test_azure_cdn_purge(self, make_purge_call_mock):
|
|
178
187
|
backends = get_backends(
|
|
@@ -214,7 +223,7 @@ class TestBackendConfiguration(TestCase):
|
|
|
214
223
|
self.assertEqual(call_args[1], ["/home/events/christmas/?test=1", "/blog/"])
|
|
215
224
|
|
|
216
225
|
@mock.patch(
|
|
217
|
-
"wagtail.contrib.frontend_cache.backends.AzureFrontDoorBackend._make_purge_call"
|
|
226
|
+
"wagtail.contrib.frontend_cache.backends.azure.AzureFrontDoorBackend._make_purge_call"
|
|
218
227
|
)
|
|
219
228
|
def test_azure_front_door_purge(self, make_purge_call_mock):
|
|
220
229
|
backends = get_backends(
|
|
@@ -285,7 +294,7 @@ class TestBackendConfiguration(TestCase):
|
|
|
285
294
|
log_output.output[0],
|
|
286
295
|
)
|
|
287
296
|
|
|
288
|
-
@mock.patch("wagtail.contrib.frontend_cache.backends.urlopen")
|
|
297
|
+
@mock.patch("wagtail.contrib.frontend_cache.backends.http.urlopen")
|
|
289
298
|
def _test_http_with_side_effect(self, urlopen_mock, urlopen_side_effect):
|
|
290
299
|
# given a backends configuration with one HTTP backend
|
|
291
300
|
backends = get_backends(
|
|
@@ -323,7 +332,7 @@ class TestBackendConfiguration(TestCase):
|
|
|
323
332
|
)
|
|
324
333
|
|
|
325
334
|
@mock.patch(
|
|
326
|
-
"wagtail.contrib.frontend_cache.backends.CloudfrontBackend._create_invalidation"
|
|
335
|
+
"wagtail.contrib.frontend_cache.backends.cloudfront.CloudfrontBackend._create_invalidation"
|
|
327
336
|
)
|
|
328
337
|
def test_cloudfront_distribution_id_mapping(self, _create_invalidation):
|
|
329
338
|
backends = get_backends(
|
|
@@ -336,15 +345,31 @@ class TestBackendConfiguration(TestCase):
|
|
|
336
345
|
},
|
|
337
346
|
}
|
|
338
347
|
)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
348
|
+
with self.assertWarnsMessage(
|
|
349
|
+
RemovedInWagtail70Warning,
|
|
350
|
+
"Using a `DISTRIBUTION_ID` mapping is deprecated - use `HOSTNAMES` in combination with multiple backends instead.",
|
|
351
|
+
):
|
|
352
|
+
backends.get("cloudfront").purge(
|
|
353
|
+
"http://www.wagtail.org/home/events/christmas/"
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
with self.assertWarnsMessage(
|
|
357
|
+
RemovedInWagtail70Warning,
|
|
358
|
+
"Using a `DISTRIBUTION_ID` mapping is deprecated - use `HOSTNAMES` in combination with multiple backends instead.",
|
|
359
|
+
):
|
|
360
|
+
backends.get("cloudfront").purge("http://torchbox.com/blog/")
|
|
343
361
|
|
|
344
362
|
_create_invalidation.assert_called_once_with(
|
|
345
363
|
"frontend", ["/home/events/christmas/"]
|
|
346
364
|
)
|
|
347
365
|
|
|
366
|
+
self.assertTrue(
|
|
367
|
+
backends.get("cloudfront").invalidates_hostname("www.wagtail.org")
|
|
368
|
+
)
|
|
369
|
+
self.assertFalse(
|
|
370
|
+
backends.get("cloudfront").invalidates_hostname("torchbox.com")
|
|
371
|
+
)
|
|
372
|
+
|
|
348
373
|
def test_multiple(self):
|
|
349
374
|
backends = get_backends(
|
|
350
375
|
backend_settings={
|
|
@@ -396,17 +421,11 @@ PURGED_URLS = []
|
|
|
396
421
|
|
|
397
422
|
|
|
398
423
|
class MockBackend(BaseBackend):
|
|
399
|
-
def __init__(self, config):
|
|
400
|
-
pass
|
|
401
|
-
|
|
402
424
|
def purge(self, url):
|
|
403
425
|
PURGED_URLS.append(url)
|
|
404
426
|
|
|
405
427
|
|
|
406
428
|
class MockCloudflareBackend(CloudflareBackend):
|
|
407
|
-
def __init__(self, config):
|
|
408
|
-
pass
|
|
409
|
-
|
|
410
429
|
def _purge_urls(self, urls):
|
|
411
430
|
if len(urls) > self.CHUNK_SIZE:
|
|
412
431
|
raise Exception("Cloudflare backend is not chunking requests as expected")
|
|
@@ -465,11 +484,34 @@ class TestCachePurgingFunctions(TestCase):
|
|
|
465
484
|
],
|
|
466
485
|
)
|
|
467
486
|
|
|
487
|
+
@override_settings(
|
|
488
|
+
WAGTAILFRONTENDCACHE={
|
|
489
|
+
"varnish": {
|
|
490
|
+
"BACKEND": "wagtail.contrib.frontend_cache.tests.MockBackend",
|
|
491
|
+
"HOSTNAMES": ["example.com"],
|
|
492
|
+
},
|
|
493
|
+
}
|
|
494
|
+
)
|
|
495
|
+
def test_invalidate_specific_location(self):
|
|
496
|
+
with self.assertLogs(level="INFO") as log_output:
|
|
497
|
+
purge_url_from_cache("http://localhost/foo")
|
|
498
|
+
|
|
499
|
+
self.assertEqual(PURGED_URLS, [])
|
|
500
|
+
self.assertIn(
|
|
501
|
+
"Unable to find purge backend for localhost",
|
|
502
|
+
log_output.output[0],
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
purge_url_from_cache("http://example.com/foo")
|
|
506
|
+
self.assertEqual(PURGED_URLS, ["http://example.com/foo"])
|
|
507
|
+
|
|
468
508
|
|
|
469
509
|
@override_settings(
|
|
470
510
|
WAGTAILFRONTENDCACHE={
|
|
471
511
|
"cloudflare": {
|
|
472
512
|
"BACKEND": "wagtail.contrib.frontend_cache.tests.MockCloudflareBackend",
|
|
513
|
+
"ZONEID": "zone",
|
|
514
|
+
"BEARER_TOKEN": "token",
|
|
473
515
|
},
|
|
474
516
|
}
|
|
475
517
|
)
|
|
@@ -634,7 +676,7 @@ class TestPurgeBatchClass(TestCase):
|
|
|
634
676
|
],
|
|
635
677
|
)
|
|
636
678
|
|
|
637
|
-
@mock.patch("wagtail.contrib.frontend_cache.backends.requests.delete")
|
|
679
|
+
@mock.patch("wagtail.contrib.frontend_cache.backends.cloudflare.requests.delete")
|
|
638
680
|
def test_http_error_on_cloudflare_purge_batch(self, requests_delete_mock):
|
|
639
681
|
backend_settings = {
|
|
640
682
|
"cloudflare": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import re
|
|
3
|
-
from
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
4
5
|
|
|
5
6
|
from django.conf import settings
|
|
6
7
|
from django.core.exceptions import ImproperlyConfigured
|
|
@@ -79,13 +80,12 @@ def purge_urls_from_cache(urls, backend_settings=None, backends=None):
|
|
|
79
80
|
# Purge the given url for each managed language
|
|
80
81
|
for isocode in languages:
|
|
81
82
|
for url in urls:
|
|
82
|
-
up =
|
|
83
|
-
new_url =
|
|
83
|
+
up = urlsplit(url)
|
|
84
|
+
new_url = urlunsplit(
|
|
84
85
|
(
|
|
85
86
|
up.scheme,
|
|
86
87
|
up.netloc,
|
|
87
88
|
re.sub(langs_regex, "/%s/" % isocode, up.path),
|
|
88
|
-
up.params,
|
|
89
89
|
up.query,
|
|
90
90
|
up.fragment,
|
|
91
91
|
)
|
|
@@ -100,11 +100,29 @@ def purge_urls_from_cache(urls, backend_settings=None, backends=None):
|
|
|
100
100
|
|
|
101
101
|
urls = new_urls
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
for url in urls:
|
|
105
|
-
logger.info("[%s] Purging URL: %s", backend_name, url)
|
|
103
|
+
urls_by_hostname = defaultdict(list)
|
|
106
104
|
|
|
107
|
-
|
|
105
|
+
for url in urls:
|
|
106
|
+
urls_by_hostname[urlsplit(url).netloc].append(url)
|
|
107
|
+
|
|
108
|
+
backends = get_backends(backend_settings, backends)
|
|
109
|
+
|
|
110
|
+
for hostname, urls in urls_by_hostname.items():
|
|
111
|
+
backends_for_hostname = {
|
|
112
|
+
backend_name: backend
|
|
113
|
+
for backend_name, backend in backends.items()
|
|
114
|
+
if backend.invalidates_hostname(hostname)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if not backends_for_hostname:
|
|
118
|
+
logger.info("Unable to find purge backend for %s", hostname)
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
for backend_name, backend in backends_for_hostname.items():
|
|
122
|
+
for url in urls:
|
|
123
|
+
logger.info("[%s] Purging URL: %s", backend_name, url)
|
|
124
|
+
|
|
125
|
+
backend.purge_batch(urls)
|
|
108
126
|
|
|
109
127
|
|
|
110
128
|
def _get_page_cached_urls(page):
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import django_filters
|
|
2
2
|
from django import forms
|
|
3
|
+
from django.db.models import QuerySet
|
|
3
4
|
from django.utils.translation import gettext as _
|
|
4
5
|
|
|
5
6
|
from wagtail.admin.filters import WagtailFilterSet
|
|
6
7
|
from wagtail.contrib.redirects.models import Redirect
|
|
7
|
-
from wagtail.models import Site
|
|
8
|
+
from wagtail.models import Page, Site
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_redirect_pages_queryset(request) -> QuerySet[Page]:
|
|
12
|
+
redirect_page_pks = (
|
|
13
|
+
Redirect.objects.filter(redirect_page__isnull=False)
|
|
14
|
+
.order_by()
|
|
15
|
+
.values_list("redirect_page", flat=True)
|
|
16
|
+
.distinct()
|
|
17
|
+
)
|
|
18
|
+
return Page.objects.filter(pk__in=redirect_page_pks)
|
|
8
19
|
|
|
9
20
|
|
|
10
21
|
class RedirectsReportFilterSet(WagtailFilterSet):
|
|
22
|
+
redirect_page = django_filters.ModelChoiceFilter(
|
|
23
|
+
field_name="redirect_page", queryset=get_redirect_pages_queryset
|
|
24
|
+
)
|
|
11
25
|
is_permanent = django_filters.ChoiceFilter(
|
|
12
26
|
label=_("Type"),
|
|
13
27
|
method="filter_type",
|
|
@@ -120,11 +120,11 @@ msgstr "عذرًا ، لا توجد عمليات إعادة توجيه تطاب
|
|
|
120
120
|
|
|
121
121
|
#, python-format
|
|
122
122
|
msgid ""
|
|
123
|
-
"No redirects have been created. Why not <a
|
|
124
|
-
"
|
|
123
|
+
"No redirects have been created. Why not <a "
|
|
124
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
|
|
125
125
|
msgstr ""
|
|
126
|
-
"لم يتم إنشاء عمليات إعادة توجيه. لماذا لا<a
|
|
127
|
-
"
|
|
126
|
+
"لم يتم إنشاء عمليات إعادة توجيه. لماذا لا<a "
|
|
127
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\"> تضيف واحدة</a>؟"
|
|
128
128
|
|
|
129
129
|
msgid "Site"
|
|
130
130
|
msgstr "موقع"
|
|
@@ -17,9 +17,9 @@ msgstr ""
|
|
|
17
17
|
"Content-Type: text/plain; charset=UTF-8\n"
|
|
18
18
|
"Content-Transfer-Encoding: 8bit\n"
|
|
19
19
|
"Language: be\n"
|
|
20
|
-
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 &&
|
|
21
|
-
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) ||
|
|
22
|
-
"%100>=11 && n%100<=14)? 2 : 3);\n"
|
|
20
|
+
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
|
21
|
+
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
|
|
22
|
+
"(n%100>=11 && n%100<=14)? 2 : 3);\n"
|
|
23
23
|
|
|
24
24
|
msgid "Type"
|
|
25
25
|
msgstr "Тып"
|
|
@@ -64,11 +64,11 @@ msgstr "До"
|
|
|
64
64
|
|
|
65
65
|
#, python-format
|
|
66
66
|
msgid ""
|
|
67
|
-
"No redirects have been created. Why not <a
|
|
68
|
-
"
|
|
67
|
+
"No redirects have been created. Why not <a "
|
|
68
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
|
|
69
69
|
msgstr ""
|
|
70
|
-
"Няма създадени пренасочвания. Защо не <a
|
|
71
|
-
"
|
|
70
|
+
"Няма създадени пренасочвания. Защо не <a "
|
|
71
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">добавите един сега</a>?"
|
|
72
72
|
|
|
73
73
|
msgid "The redirect could not be saved due to errors."
|
|
74
74
|
msgstr "Пренасочването не бе запазено поради грешки."
|
|
@@ -187,11 +187,11 @@ msgstr "Ho sentim, cap redirecció coincideix amb \"<em>%(query_string)s</em>\""
|
|
|
187
187
|
|
|
188
188
|
#, python-format
|
|
189
189
|
msgid ""
|
|
190
|
-
"No redirects have been created. Why not <a
|
|
191
|
-
"
|
|
190
|
+
"No redirects have been created. Why not <a "
|
|
191
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
|
|
192
192
|
msgstr ""
|
|
193
|
-
"No s'ha creat cap redirecció. Voleu <a
|
|
194
|
-
"
|
|
193
|
+
"No s'ha creat cap redirecció. Voleu <a "
|
|
194
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">afegir-ne una</a>?"
|
|
195
195
|
|
|
196
196
|
msgid "Site"
|
|
197
197
|
msgstr "Lloc"
|
|
@@ -162,11 +162,11 @@ msgstr ""
|
|
|
162
162
|
|
|
163
163
|
#, python-format
|
|
164
164
|
msgid ""
|
|
165
|
-
"No redirects have been created. Why not <a
|
|
166
|
-
"
|
|
165
|
+
"No redirects have been created. Why not <a "
|
|
166
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
|
|
167
167
|
msgstr ""
|
|
168
|
-
"Nebyly nalezeny žádná přesměrování. Nové přesměrování můžete přidat <a
|
|
169
|
-
"
|
|
168
|
+
"Nebyly nalezeny žádná přesměrování. Nové přesměrování můžete přidat <a "
|
|
169
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">zde</a>?"
|
|
170
170
|
|
|
171
171
|
msgid "Site"
|
|
172
172
|
msgstr "Web"
|
|
@@ -168,16 +168,16 @@ msgstr "Parhau"
|
|
|
168
168
|
#, python-format
|
|
169
169
|
msgid "Sorry, no redirects match \"<em>%(query_string)s</em>\""
|
|
170
170
|
msgstr ""
|
|
171
|
-
"Mae'n ddrwg gennym, nid oes unrhyw ailgyfeiriadau yn cyfateb
|
|
172
|
-
"
|
|
171
|
+
"Mae'n ddrwg gennym, nid oes unrhyw ailgyfeiriadau yn cyfateb "
|
|
172
|
+
"\"<em>%(query_string)s</em>\""
|
|
173
173
|
|
|
174
174
|
#, python-format
|
|
175
175
|
msgid ""
|
|
176
|
-
"No redirects have been created. Why not <a
|
|
177
|
-
"
|
|
176
|
+
"No redirects have been created. Why not <a "
|
|
177
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
|
|
178
178
|
msgstr ""
|
|
179
|
-
"Nid oes unrhyw ailgyfeiriadau wedi'u creu. Pam ddim <a
|
|
180
|
-
"
|
|
179
|
+
"Nid oes unrhyw ailgyfeiriadau wedi'u creu. Pam ddim <a "
|
|
180
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">ychwanegu un</a>?"
|
|
181
181
|
|
|
182
182
|
msgid "Site"
|
|
183
183
|
msgstr "Safle"
|
|
@@ -209,11 +209,12 @@ msgstr ""
|
|
|
209
209
|
|
|
210
210
|
#, python-format
|
|
211
211
|
msgid ""
|
|
212
|
-
"No redirects have been created. Why not <a
|
|
213
|
-
"
|
|
212
|
+
"No redirects have been created. Why not <a "
|
|
213
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
|
|
214
214
|
msgstr ""
|
|
215
|
-
"Sie haben noch keine Weiterleitung erstellt.<a
|
|
216
|
-
"
|
|
215
|
+
"Sie haben noch keine Weiterleitung erstellt.<a "
|
|
216
|
+
"href=\"%(wagtailredirects_add_redirect_url)s\">Erstellen Sie doch jetzt eine!"
|
|
217
|
+
"</a>"
|
|
217
218
|
|
|
218
219
|
msgid "Site"
|
|
219
220
|
msgstr "Seite"
|