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.
Files changed (644) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/actions/copy_for_translation.py +15 -1
  3. wagtail/admin/checks.py +20 -30
  4. wagtail/admin/forms/pages.py +10 -0
  5. wagtail/admin/icons.py +43 -0
  6. wagtail/admin/locale/ar/LC_MESSAGES/django.po +2 -2
  7. wagtail/admin/locale/be/LC_MESSAGES/django.po +7 -7
  8. wagtail/admin/locale/be/LC_MESSAGES/djangojs.po +3 -3
  9. wagtail/admin/locale/ca/LC_MESSAGES/django.mo +0 -0
  10. wagtail/admin/locale/ca/LC_MESSAGES/django.po +51 -50
  11. wagtail/admin/locale/cs/LC_MESSAGES/django.po +10 -8
  12. wagtail/admin/locale/de/LC_MESSAGES/django.po +49 -47
  13. wagtail/admin/locale/dv/LC_MESSAGES/django.po +8 -8
  14. wagtail/admin/locale/el/LC_MESSAGES/django.po +4 -4
  15. wagtail/admin/locale/en/LC_MESSAGES/django.po +405 -295
  16. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +21 -3
  17. wagtail/admin/locale/es/LC_MESSAGES/django.po +40 -39
  18. wagtail/admin/locale/es_419/LC_MESSAGES/django.po +8 -8
  19. wagtail/admin/locale/et/LC_MESSAGES/django.po +14 -12
  20. wagtail/admin/locale/fa/LC_MESSAGES/django.mo +0 -0
  21. wagtail/admin/locale/fa/LC_MESSAGES/django.po +93 -19
  22. wagtail/admin/locale/fa/LC_MESSAGES/djangojs.mo +0 -0
  23. wagtail/admin/locale/fa/LC_MESSAGES/djangojs.po +5 -1
  24. wagtail/admin/locale/fi/LC_MESSAGES/django.po +18 -18
  25. wagtail/admin/locale/fr/LC_MESSAGES/django.mo +0 -0
  26. wagtail/admin/locale/fr/LC_MESSAGES/django.po +134 -46
  27. wagtail/admin/locale/gl/LC_MESSAGES/django.po +55 -54
  28. wagtail/admin/locale/hr_HR/LC_MESSAGES/django.po +13 -12
  29. wagtail/admin/locale/hr_HR/LC_MESSAGES/djangojs.po +2 -2
  30. wagtail/admin/locale/hu/LC_MESSAGES/django.po +45 -42
  31. wagtail/admin/locale/id_ID/LC_MESSAGES/django.po +6 -6
  32. wagtail/admin/locale/is_IS/LC_MESSAGES/django.po +53 -51
  33. wagtail/admin/locale/it/LC_MESSAGES/django.po +56 -55
  34. wagtail/admin/locale/ja/LC_MESSAGES/django.po +2 -2
  35. wagtail/admin/locale/ko/LC_MESSAGES/django.po +18 -17
  36. wagtail/admin/locale/lt/LC_MESSAGES/django.po +4 -4
  37. wagtail/admin/locale/nb/LC_MESSAGES/django.po +22 -22
  38. wagtail/admin/locale/nl/LC_MESSAGES/django.po +44 -41
  39. wagtail/admin/locale/pl/LC_MESSAGES/django.po +49 -47
  40. wagtail/admin/locale/pl/LC_MESSAGES/djangojs.po +3 -3
  41. wagtail/admin/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  42. wagtail/admin/locale/pt_BR/LC_MESSAGES/django.po +46 -26
  43. wagtail/admin/locale/pt_PT/LC_MESSAGES/django.po +21 -20
  44. wagtail/admin/locale/ro/LC_MESSAGES/django.po +51 -50
  45. wagtail/admin/locale/ru/LC_MESSAGES/django.po +60 -59
  46. wagtail/admin/locale/ru/LC_MESSAGES/djangojs.po +3 -3
  47. wagtail/admin/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  48. wagtail/admin/locale/sk_SK/LC_MESSAGES/django.po +15 -5
  49. wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
  50. wagtail/admin/locale/sl/LC_MESSAGES/django.po +86 -39
  51. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +2 -2
  52. wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
  53. wagtail/admin/locale/sv/LC_MESSAGES/django.po +117 -41
  54. wagtail/admin/locale/sv/LC_MESSAGES/djangojs.mo +0 -0
  55. wagtail/admin/locale/sv/LC_MESSAGES/djangojs.po +5 -2
  56. wagtail/admin/locale/tet/LC_MESSAGES/django.po +2 -2
  57. wagtail/admin/locale/th/LC_MESSAGES/django.po +4 -4
  58. wagtail/admin/locale/tr/LC_MESSAGES/django.po +4 -4
  59. wagtail/admin/locale/tr_TR/LC_MESSAGES/django.po +4 -4
  60. wagtail/admin/locale/uk/LC_MESSAGES/django.po +11 -10
  61. wagtail/admin/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  62. wagtail/admin/locale/zh_Hans/LC_MESSAGES/django.po +84 -13
  63. wagtail/admin/locale/zh_Hant/LC_MESSAGES/django.po +2 -2
  64. wagtail/admin/menu.py +2 -2
  65. wagtail/admin/migrations/0004_editingsession.py +57 -0
  66. wagtail/admin/migrations/0005_editingsession_is_editing.py +18 -0
  67. wagtail/admin/models.py +36 -3
  68. wagtail/admin/rich_text/editors/draftail/__init__.py +2 -20
  69. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  70. wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
  71. wagtail/admin/static/wagtailadmin/js/chooser-modal.js +1 -1
  72. wagtail/admin/static/wagtailadmin/js/chooser-widget-telepath.js +1 -1
  73. wagtail/admin/static/wagtailadmin/js/chooser-widget.js +1 -1
  74. wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
  75. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  76. wagtail/admin/static/wagtailadmin/js/date-time-chooser.js +1 -1
  77. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  78. wagtail/admin/static/wagtailadmin/js/expanding-formset.js +1 -1
  79. wagtail/admin/static/wagtailadmin/js/filtered-select.js +1 -1
  80. wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
  81. wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
  82. wagtail/admin/static/wagtailadmin/js/page-chooser-telepath.js +1 -1
  83. wagtail/admin/static/wagtailadmin/js/page-chooser.js +1 -1
  84. wagtail/admin/static/wagtailadmin/js/preview-panel.js +2 -1
  85. wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +11 -0
  86. wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
  87. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  88. wagtail/admin/static/wagtailadmin/js/task-chooser-modal.js +1 -1
  89. wagtail/admin/static/wagtailadmin/js/task-chooser.js +1 -1
  90. wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
  91. wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
  92. wagtail/admin/static/wagtailadmin/js/userbar.js +2 -1
  93. wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +11 -0
  94. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  95. wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +0 -12
  96. wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
  97. wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
  98. wagtail/admin/templates/wagtailadmin/collection_privacy/ancestor_privacy.html +2 -6
  99. wagtail/admin/templates/wagtailadmin/generic/index_results.html +1 -17
  100. wagtail/admin/templates/wagtailadmin/generic/listing_results.html +20 -1
  101. wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +2 -11
  102. wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +2 -6
  103. wagtail/admin/templates/wagtailadmin/page_privacy/no_privacy.html +2 -0
  104. wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
  105. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -1
  106. wagtail/admin/templates/wagtailadmin/reports/aging_pages_results.html +54 -0
  107. wagtail/admin/templates/wagtailadmin/reports/base_page_report.html +1 -17
  108. wagtail/admin/templates/wagtailadmin/reports/base_page_report_results.html +10 -0
  109. wagtail/admin/templates/wagtailadmin/reports/base_report.html +1 -40
  110. wagtail/admin/templates/wagtailadmin/reports/base_report_results.html +1 -0
  111. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +21 -27
  112. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +48 -54
  113. wagtail/admin/templates/wagtailadmin/reports/{locked_pages.html → locked_pages_results.html} +3 -3
  114. wagtail/admin/templates/wagtailadmin/reports/page_types_usage_results.html +10 -0
  115. wagtail/admin/templates/wagtailadmin/reports/site_history_results.html +53 -0
  116. wagtail/admin/templates/wagtailadmin/reports/workflow_results.html +74 -0
  117. wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +56 -0
  118. wagtail/admin/templates/wagtailadmin/shared/_workflow_init.html +8 -44
  119. wagtail/admin/templates/wagtailadmin/shared/avatar.html +11 -1
  120. wagtail/admin/templates/wagtailadmin/shared/dialog/dialog.html +5 -4
  121. wagtail/admin/templates/wagtailadmin/shared/dropdown/dropdown_button.html +2 -1
  122. wagtail/admin/templates/wagtailadmin/shared/editing_sessions/list.html +132 -0
  123. wagtail/admin/templates/wagtailadmin/shared/editing_sessions/module.html +44 -0
  124. wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +7 -1
  125. wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +1 -1
  126. wagtail/admin/templates/wagtailadmin/shared/side_panels/checks.html +32 -16
  127. wagtail/admin/templates/wagtailadmin/skeleton.html +1 -1
  128. wagtail/admin/templates/wagtailadmin/userbar/item_accessibility.html +9 -11
  129. wagtail/admin/templatetags/wagtailadmin_tags.py +13 -2
  130. wagtail/admin/tests/formats/en/__init__.py +0 -0
  131. wagtail/admin/tests/formats/en/formats.py +1 -0
  132. wagtail/admin/tests/pages/test_create_page.py +47 -0
  133. wagtail/admin/tests/pages/test_edit_page.py +10 -8
  134. wagtail/admin/tests/pages/test_parent_page_chooser_view.py +45 -1
  135. wagtail/admin/tests/test_checks.py +53 -3
  136. wagtail/admin/tests/test_collections_views.py +62 -1
  137. wagtail/admin/tests/test_edit_handlers.py +37 -0
  138. wagtail/admin/tests/test_editing_sessions.py +1336 -0
  139. wagtail/admin/tests/test_icon_sprite.py +12 -21
  140. wagtail/admin/tests/test_page_chooser.py +309 -7
  141. wagtail/admin/tests/test_privacy.py +82 -0
  142. wagtail/admin/tests/test_reports_views.py +464 -70
  143. wagtail/admin/tests/test_userbar.py +93 -6
  144. wagtail/admin/tests/test_workflows.py +223 -33
  145. wagtail/admin/tests/viewsets/test_model_viewset.py +151 -2
  146. wagtail/admin/ui/editing_sessions.py +57 -0
  147. wagtail/admin/urls/__init__.py +9 -15
  148. wagtail/admin/urls/editing_sessions.py +17 -0
  149. wagtail/admin/urls/reports.py +33 -1
  150. wagtail/admin/userbar.py +77 -20
  151. wagtail/admin/views/chooser.py +49 -22
  152. wagtail/admin/views/collections.py +0 -11
  153. wagtail/admin/views/editing_sessions.py +193 -0
  154. wagtail/admin/views/generic/__init__.py +1 -0
  155. wagtail/admin/views/generic/base.py +3 -2
  156. wagtail/admin/views/generic/history.py +9 -3
  157. wagtail/admin/views/generic/mixins.py +44 -3
  158. wagtail/admin/views/generic/models.py +46 -72
  159. wagtail/admin/views/generic/permissions.py +20 -10
  160. wagtail/admin/views/home.py +2 -31
  161. wagtail/admin/views/page_privacy.py +20 -5
  162. wagtail/admin/views/pages/choose_parent.py +62 -0
  163. wagtail/admin/views/pages/edit.py +28 -0
  164. wagtail/admin/views/reports/aging_pages.py +6 -10
  165. wagtail/admin/views/reports/audit_logging.py +13 -42
  166. wagtail/admin/views/reports/base.py +31 -4
  167. wagtail/admin/views/reports/locked_pages.py +5 -8
  168. wagtail/admin/views/reports/page_types_usage.py +6 -10
  169. wagtail/admin/views/reports/workflows.py +36 -12
  170. wagtail/admin/viewsets/base.py +8 -3
  171. wagtail/admin/viewsets/chooser.py +1 -1
  172. wagtail/admin/viewsets/model.py +26 -1
  173. wagtail/admin/wagtail_hooks.py +2 -1
  174. wagtail/api/v2/filters.py +6 -0
  175. wagtail/api/v2/tests/test_documents.py +1 -1
  176. wagtail/api/v2/tests/test_images.py +1 -1
  177. wagtail/api/v2/tests/test_pages.py +11 -1
  178. wagtail/api/v2/utils.py +2 -2
  179. wagtail/blocks/base.py +35 -12
  180. wagtail/blocks/definition_lookup.py +85 -0
  181. wagtail/blocks/list_block.py +12 -0
  182. wagtail/blocks/migrations/migrate_operation.py +2 -0
  183. wagtail/blocks/stream_block.py +19 -0
  184. wagtail/blocks/struct_block.py +19 -0
  185. wagtail/contrib/forms/locale/be/LC_MESSAGES/django.po +3 -3
  186. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +1 -1
  187. wagtail/contrib/forms/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  188. wagtail/contrib/forms/locale/pl/LC_MESSAGES/django.po +3 -3
  189. wagtail/contrib/forms/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  190. wagtail/contrib/forms/locale/pt_BR/LC_MESSAGES/django.po +2 -2
  191. wagtail/contrib/forms/locale/ru/LC_MESSAGES/django.po +3 -3
  192. wagtail/contrib/forms/locale/sl/LC_MESSAGES/django.po +2 -2
  193. wagtail/contrib/frontend_cache/backends/__init__.py +5 -0
  194. wagtail/contrib/frontend_cache/backends/azure.py +179 -0
  195. wagtail/contrib/frontend_cache/backends/base.py +28 -0
  196. wagtail/contrib/frontend_cache/backends/cloudflare.py +114 -0
  197. wagtail/contrib/frontend_cache/backends/cloudfront.py +99 -0
  198. wagtail/contrib/frontend_cache/backends/http.py +64 -0
  199. wagtail/contrib/frontend_cache/tests.py +59 -17
  200. wagtail/contrib/frontend_cache/utils.py +26 -8
  201. wagtail/contrib/redirects/filters.py +15 -1
  202. wagtail/contrib/redirects/locale/ar/LC_MESSAGES/django.po +4 -4
  203. wagtail/contrib/redirects/locale/be/LC_MESSAGES/django.po +3 -3
  204. wagtail/contrib/redirects/locale/bg/LC_MESSAGES/django.po +4 -4
  205. wagtail/contrib/redirects/locale/ca/LC_MESSAGES/django.po +4 -4
  206. wagtail/contrib/redirects/locale/cs/LC_MESSAGES/django.po +4 -4
  207. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +6 -6
  208. wagtail/contrib/redirects/locale/de/LC_MESSAGES/django.po +5 -4
  209. wagtail/contrib/redirects/locale/el/LC_MESSAGES/django.po +7 -7
  210. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +37 -72
  211. wagtail/contrib/redirects/locale/es/LC_MESSAGES/django.po +6 -6
  212. wagtail/contrib/redirects/locale/et/LC_MESSAGES/django.po +4 -4
  213. wagtail/contrib/redirects/locale/fa/LC_MESSAGES/django.mo +0 -0
  214. wagtail/contrib/redirects/locale/fa/LC_MESSAGES/django.po +18 -5
  215. wagtail/contrib/redirects/locale/fi/LC_MESSAGES/django.po +6 -6
  216. wagtail/contrib/redirects/locale/fr/LC_MESSAGES/django.po +4 -4
  217. wagtail/contrib/redirects/locale/gl/LC_MESSAGES/django.po +4 -4
  218. wagtail/contrib/redirects/locale/hr_HR/LC_MESSAGES/django.po +8 -8
  219. wagtail/contrib/redirects/locale/hu/LC_MESSAGES/django.po +6 -6
  220. wagtail/contrib/redirects/locale/id_ID/LC_MESSAGES/django.po +4 -4
  221. wagtail/contrib/redirects/locale/is_IS/LC_MESSAGES/django.po +6 -6
  222. wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.po +4 -4
  223. wagtail/contrib/redirects/locale/ja/LC_MESSAGES/django.po +2 -2
  224. wagtail/contrib/redirects/locale/ko/LC_MESSAGES/django.po +4 -4
  225. wagtail/contrib/redirects/locale/lt/LC_MESSAGES/django.po +4 -4
  226. wagtail/contrib/redirects/locale/mn/LC_MESSAGES/django.po +4 -4
  227. wagtail/contrib/redirects/locale/nb/LC_MESSAGES/django.po +4 -4
  228. wagtail/contrib/redirects/locale/nl/LC_MESSAGES/django.po +4 -4
  229. wagtail/contrib/redirects/locale/pl/LC_MESSAGES/django.po +9 -9
  230. wagtail/contrib/redirects/locale/pt_BR/LC_MESSAGES/django.po +5 -5
  231. wagtail/contrib/redirects/locale/pt_PT/LC_MESSAGES/django.po +4 -4
  232. wagtail/contrib/redirects/locale/ro/LC_MESSAGES/django.po +4 -4
  233. wagtail/contrib/redirects/locale/ru/LC_MESSAGES/django.po +7 -7
  234. wagtail/contrib/redirects/locale/sk_SK/LC_MESSAGES/django.po +4 -4
  235. wagtail/contrib/redirects/locale/sl/LC_MESSAGES/django.po +6 -6
  236. wagtail/contrib/redirects/locale/sr/LC_MESSAGES/django.po +2 -2
  237. wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.po +4 -4
  238. wagtail/contrib/redirects/locale/tet/LC_MESSAGES/django.po +4 -4
  239. wagtail/contrib/redirects/locale/th/LC_MESSAGES/django.po +4 -4
  240. wagtail/contrib/redirects/locale/tr/LC_MESSAGES/django.po +4 -4
  241. wagtail/contrib/redirects/locale/tr_TR/LC_MESSAGES/django.po +4 -4
  242. wagtail/contrib/redirects/locale/uk/LC_MESSAGES/django.po +4 -4
  243. wagtail/contrib/redirects/locale/zh/LC_MESSAGES/django.po +4 -4
  244. wagtail/contrib/redirects/locale/zh_Hans/LC_MESSAGES/django.po +4 -4
  245. wagtail/contrib/redirects/locale/zh_Hant/LC_MESSAGES/django.po +4 -4
  246. wagtail/contrib/redirects/models.py +6 -5
  247. wagtail/contrib/redirects/templates/wagtailredirects/edit.html +1 -38
  248. wagtail/contrib/redirects/tests/test_redirects.py +141 -1
  249. wagtail/contrib/redirects/urls.py +1 -2
  250. wagtail/contrib/redirects/views.py +39 -80
  251. wagtail/contrib/routable_page/models.py +6 -4
  252. wagtail/contrib/routable_page/tests.py +11 -0
  253. wagtail/contrib/search_promotions/locale/ar/LC_MESSAGES/django.po +4 -4
  254. wagtail/contrib/search_promotions/locale/be/LC_MESSAGES/django.po +7 -7
  255. wagtail/contrib/search_promotions/locale/ca/LC_MESSAGES/django.po +8 -8
  256. wagtail/contrib/search_promotions/locale/cs/LC_MESSAGES/django.po +2 -2
  257. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +4 -4
  258. wagtail/contrib/search_promotions/locale/de/LC_MESSAGES/django.po +6 -6
  259. wagtail/contrib/search_promotions/locale/el/LC_MESSAGES/django.po +4 -4
  260. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +1 -1
  261. wagtail/contrib/search_promotions/locale/es/LC_MESSAGES/django.po +6 -6
  262. wagtail/contrib/search_promotions/locale/et/LC_MESSAGES/django.po +4 -4
  263. wagtail/contrib/search_promotions/locale/fa/LC_MESSAGES/django.po +4 -4
  264. wagtail/contrib/search_promotions/locale/fi/LC_MESSAGES/django.po +6 -6
  265. wagtail/contrib/search_promotions/locale/fr/LC_MESSAGES/django.mo +0 -0
  266. wagtail/contrib/search_promotions/locale/fr/LC_MESSAGES/django.po +9 -6
  267. wagtail/contrib/search_promotions/locale/gl/LC_MESSAGES/django.po +6 -6
  268. wagtail/contrib/search_promotions/locale/hr_HR/LC_MESSAGES/django.po +8 -8
  269. wagtail/contrib/search_promotions/locale/hu/LC_MESSAGES/django.po +4 -4
  270. wagtail/contrib/search_promotions/locale/id_ID/LC_MESSAGES/django.po +4 -4
  271. wagtail/contrib/search_promotions/locale/is_IS/LC_MESSAGES/django.po +8 -8
  272. wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +6 -6
  273. wagtail/contrib/search_promotions/locale/ja/LC_MESSAGES/django.po +4 -4
  274. wagtail/contrib/search_promotions/locale/ko/LC_MESSAGES/django.po +4 -4
  275. wagtail/contrib/search_promotions/locale/lt/LC_MESSAGES/django.po +6 -6
  276. wagtail/contrib/search_promotions/locale/nb/LC_MESSAGES/django.po +4 -4
  277. wagtail/contrib/search_promotions/locale/nl/LC_MESSAGES/django.po +6 -6
  278. wagtail/contrib/search_promotions/locale/pl/LC_MESSAGES/django.po +9 -9
  279. wagtail/contrib/search_promotions/locale/pt_BR/LC_MESSAGES/django.po +4 -4
  280. wagtail/contrib/search_promotions/locale/pt_PT/LC_MESSAGES/django.po +4 -4
  281. wagtail/contrib/search_promotions/locale/ro/LC_MESSAGES/django.po +4 -4
  282. wagtail/contrib/search_promotions/locale/ru/LC_MESSAGES/django.po +9 -9
  283. wagtail/contrib/search_promotions/locale/sk_SK/LC_MESSAGES/django.po +4 -4
  284. wagtail/contrib/search_promotions/locale/sl/LC_MESSAGES/django.mo +0 -0
  285. wagtail/contrib/search_promotions/locale/sl/LC_MESSAGES/django.po +62 -8
  286. wagtail/contrib/search_promotions/locale/sr/LC_MESSAGES/django.po +2 -2
  287. wagtail/contrib/search_promotions/locale/sv/LC_MESSAGES/django.mo +0 -0
  288. wagtail/contrib/search_promotions/locale/sv/LC_MESSAGES/django.po +9 -6
  289. wagtail/contrib/search_promotions/locale/th/LC_MESSAGES/django.po +4 -4
  290. wagtail/contrib/search_promotions/locale/tr/LC_MESSAGES/django.po +4 -4
  291. wagtail/contrib/search_promotions/locale/tr_TR/LC_MESSAGES/django.po +4 -4
  292. wagtail/contrib/search_promotions/locale/uk/LC_MESSAGES/django.po +4 -4
  293. wagtail/contrib/search_promotions/locale/zh_Hans/LC_MESSAGES/django.po +2 -2
  294. wagtail/contrib/search_promotions/locale/zh_Hant/LC_MESSAGES/django.po +2 -2
  295. wagtail/contrib/settings/locale/be/LC_MESSAGES/django.po +3 -3
  296. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +4 -4
  297. wagtail/contrib/settings/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  298. wagtail/contrib/settings/locale/pl/LC_MESSAGES/django.po +3 -3
  299. wagtail/contrib/settings/locale/pt_BR/LC_MESSAGES/django.po +1 -1
  300. wagtail/contrib/settings/locale/ru/LC_MESSAGES/django.po +3 -3
  301. wagtail/contrib/settings/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  302. wagtail/contrib/settings/locale/sk_SK/LC_MESSAGES/django.po +10 -1
  303. wagtail/contrib/settings/locale/sl/LC_MESSAGES/django.po +2 -2
  304. wagtail/contrib/settings/locale/sr/LC_MESSAGES/django.po +2 -2
  305. wagtail/contrib/simple_translation/locale/be/LC_MESSAGES/django.po +3 -3
  306. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +5 -1
  307. wagtail/contrib/simple_translation/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  308. wagtail/contrib/simple_translation/locale/pl/LC_MESSAGES/django.po +3 -3
  309. wagtail/contrib/simple_translation/locale/pt_BR/LC_MESSAGES/django.po +1 -1
  310. wagtail/contrib/simple_translation/locale/ru/LC_MESSAGES/django.po +3 -3
  311. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +2 -2
  312. wagtail/contrib/simple_translation/models.py +2 -1
  313. wagtail/contrib/styleguide/locale/be/LC_MESSAGES/django.po +3 -3
  314. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
  315. wagtail/contrib/styleguide/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  316. wagtail/contrib/styleguide/locale/pl/LC_MESSAGES/django.po +3 -3
  317. wagtail/contrib/styleguide/locale/ru/LC_MESSAGES/django.po +3 -3
  318. wagtail/contrib/styleguide/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  319. wagtail/contrib/styleguide/locale/sk_SK/LC_MESSAGES/django.po +5 -1
  320. wagtail/contrib/styleguide/locale/sl/LC_MESSAGES/django.po +2 -2
  321. wagtail/contrib/styleguide/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  322. wagtail/contrib/styleguide/locale/zh_Hans/LC_MESSAGES/django.po +3 -0
  323. wagtail/contrib/table_block/locale/be/LC_MESSAGES/django.po +3 -3
  324. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  325. wagtail/contrib/table_block/locale/fr/LC_MESSAGES/django.mo +0 -0
  326. wagtail/contrib/table_block/locale/fr/LC_MESSAGES/django.po +27 -1
  327. wagtail/contrib/table_block/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  328. wagtail/contrib/table_block/locale/pl/LC_MESSAGES/django.po +3 -3
  329. wagtail/contrib/table_block/locale/ru/LC_MESSAGES/django.po +3 -3
  330. wagtail/contrib/table_block/locale/sl/LC_MESSAGES/django.mo +0 -0
  331. wagtail/contrib/table_block/locale/sl/LC_MESSAGES/django.po +29 -3
  332. wagtail/contrib/table_block/static/table_block/js/table.js +1 -1
  333. wagtail/contrib/typed_table_block/blocks.py +19 -0
  334. wagtail/contrib/typed_table_block/locale/be/LC_MESSAGES/django.po +3 -3
  335. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
  336. wagtail/contrib/typed_table_block/locale/fr/LC_MESSAGES/django.mo +0 -0
  337. wagtail/contrib/typed_table_block/locale/fr/LC_MESSAGES/django.po +12 -1
  338. wagtail/contrib/typed_table_block/locale/pl/LC_MESSAGES/django.po +3 -3
  339. wagtail/contrib/typed_table_block/locale/pt_BR/LC_MESSAGES/django.po +1 -1
  340. wagtail/contrib/typed_table_block/locale/ru/LC_MESSAGES/django.po +3 -3
  341. wagtail/contrib/typed_table_block/locale/sl/LC_MESSAGES/django.mo +0 -0
  342. wagtail/contrib/typed_table_block/locale/sl/LC_MESSAGES/django.po +14 -4
  343. wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
  344. wagtail/contrib/typed_table_block/tests.py +38 -0
  345. wagtail/coreutils.py +1 -1
  346. wagtail/documents/__init__.py +1 -1
  347. wagtail/documents/locale/ar/LC_MESSAGES/django.po +8 -8
  348. wagtail/documents/locale/be/LC_MESSAGES/django.po +11 -11
  349. wagtail/documents/locale/bg/LC_MESSAGES/django.po +4 -4
  350. wagtail/documents/locale/ca/LC_MESSAGES/django.mo +0 -0
  351. wagtail/documents/locale/ca/LC_MESSAGES/django.po +12 -11
  352. wagtail/documents/locale/cs/LC_MESSAGES/django.po +6 -6
  353. wagtail/documents/locale/de/LC_MESSAGES/django.po +10 -8
  354. wagtail/documents/locale/el/LC_MESSAGES/django.po +8 -8
  355. wagtail/documents/locale/en/LC_MESSAGES/django.po +8 -8
  356. wagtail/documents/locale/es/LC_MESSAGES/django.po +8 -8
  357. wagtail/documents/locale/et/LC_MESSAGES/django.po +6 -6
  358. wagtail/documents/locale/fa/LC_MESSAGES/django.mo +0 -0
  359. wagtail/documents/locale/fa/LC_MESSAGES/django.po +17 -8
  360. wagtail/documents/locale/fi/LC_MESSAGES/django.po +10 -10
  361. wagtail/documents/locale/fr/LC_MESSAGES/django.po +6 -6
  362. wagtail/documents/locale/gl/LC_MESSAGES/django.po +8 -8
  363. wagtail/documents/locale/hr_HR/LC_MESSAGES/django.po +14 -14
  364. wagtail/documents/locale/hu/LC_MESSAGES/django.po +12 -12
  365. wagtail/documents/locale/id_ID/LC_MESSAGES/django.po +6 -6
  366. wagtail/documents/locale/is_IS/LC_MESSAGES/django.po +8 -8
  367. wagtail/documents/locale/it/LC_MESSAGES/django.po +8 -8
  368. wagtail/documents/locale/ja/LC_MESSAGES/django.po +8 -8
  369. wagtail/documents/locale/ko/LC_MESSAGES/django.po +8 -8
  370. wagtail/documents/locale/lt/LC_MESSAGES/django.po +8 -8
  371. wagtail/documents/locale/mi/LC_MESSAGES/django.po +10 -10
  372. wagtail/documents/locale/mn/LC_MESSAGES/django.po +5 -4
  373. wagtail/documents/locale/nb/LC_MESSAGES/django.po +6 -6
  374. wagtail/documents/locale/nl/LC_MESSAGES/django.po +8 -8
  375. wagtail/documents/locale/pl/LC_MESSAGES/django.po +11 -11
  376. wagtail/documents/locale/pt_BR/LC_MESSAGES/django.po +8 -8
  377. wagtail/documents/locale/pt_PT/LC_MESSAGES/django.po +8 -8
  378. wagtail/documents/locale/ro/LC_MESSAGES/django.po +8 -8
  379. wagtail/documents/locale/ru/LC_MESSAGES/django.po +9 -9
  380. wagtail/documents/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  381. wagtail/documents/locale/sk_SK/LC_MESSAGES/django.po +55 -12
  382. wagtail/documents/locale/sl/LC_MESSAGES/django.mo +0 -0
  383. wagtail/documents/locale/sl/LC_MESSAGES/django.po +30 -10
  384. wagtail/documents/locale/sr/LC_MESSAGES/django.po +2 -2
  385. wagtail/documents/locale/sv/LC_MESSAGES/django.po +6 -6
  386. wagtail/documents/locale/th/LC_MESSAGES/django.po +8 -8
  387. wagtail/documents/locale/tr/LC_MESSAGES/django.po +8 -8
  388. wagtail/documents/locale/tr_TR/LC_MESSAGES/django.po +8 -8
  389. wagtail/documents/locale/uk/LC_MESSAGES/django.po +8 -8
  390. wagtail/documents/locale/zh/LC_MESSAGES/django.po +2 -2
  391. wagtail/documents/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  392. wagtail/documents/locale/zh_Hans/LC_MESSAGES/django.po +11 -5
  393. wagtail/documents/locale/zh_Hant/LC_MESSAGES/django.po +4 -4
  394. wagtail/documents/models.py +5 -1
  395. wagtail/documents/static/wagtaildocs/js/document-chooser-modal.js +1 -1
  396. wagtail/documents/static/wagtaildocs/js/document-chooser-telepath.js +1 -1
  397. wagtail/documents/static/wagtaildocs/js/document-chooser.js +1 -1
  398. wagtail/documents/tests/test_models.py +5 -1
  399. wagtail/embeds/apps.py +2 -0
  400. wagtail/embeds/embeds.py +12 -14
  401. wagtail/embeds/finders/__init__.py +2 -0
  402. wagtail/embeds/finders/facebook.py +17 -33
  403. wagtail/embeds/finders/instagram.py +19 -16
  404. wagtail/embeds/locale/be/LC_MESSAGES/django.po +3 -3
  405. wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
  406. wagtail/embeds/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  407. wagtail/embeds/locale/pl/LC_MESSAGES/django.po +3 -3
  408. wagtail/embeds/locale/ru/LC_MESSAGES/django.po +3 -3
  409. wagtail/embeds/locale/sl/LC_MESSAGES/django.po +2 -2
  410. wagtail/embeds/signal_handlers.py +13 -0
  411. wagtail/embeds/tests/test_embeds.py +7 -7
  412. wagtail/fields.py +58 -14
  413. wagtail/images/__init__.py +1 -1
  414. wagtail/images/locale/ar/LC_MESSAGES/django.po +6 -6
  415. wagtail/images/locale/be/LC_MESSAGES/django.po +3 -3
  416. wagtail/images/locale/ca/LC_MESSAGES/django.po +8 -8
  417. wagtail/images/locale/cs/LC_MESSAGES/django.po +8 -8
  418. wagtail/images/locale/cy/LC_MESSAGES/django.po +8 -8
  419. wagtail/images/locale/de/LC_MESSAGES/django.po +6 -6
  420. wagtail/images/locale/el/LC_MESSAGES/django.po +8 -8
  421. wagtail/images/locale/en/LC_MESSAGES/django.po +34 -34
  422. wagtail/images/locale/es/LC_MESSAGES/django.po +10 -10
  423. wagtail/images/locale/et/LC_MESSAGES/django.po +8 -8
  424. wagtail/images/locale/fa/LC_MESSAGES/django.mo +0 -0
  425. wagtail/images/locale/fa/LC_MESSAGES/django.po +28 -9
  426. wagtail/images/locale/fi/LC_MESSAGES/django.po +8 -8
  427. wagtail/images/locale/fr/LC_MESSAGES/django.po +6 -6
  428. wagtail/images/locale/gl/LC_MESSAGES/django.po +8 -8
  429. wagtail/images/locale/hr_HR/LC_MESSAGES/django.po +8 -8
  430. wagtail/images/locale/hu/LC_MESSAGES/django.po +8 -8
  431. wagtail/images/locale/id_ID/LC_MESSAGES/django.po +6 -6
  432. wagtail/images/locale/is_IS/LC_MESSAGES/django.po +8 -8
  433. wagtail/images/locale/it/LC_MESSAGES/django.po +8 -8
  434. wagtail/images/locale/ja/LC_MESSAGES/django.po +8 -8
  435. wagtail/images/locale/ko/LC_MESSAGES/django.po +6 -6
  436. wagtail/images/locale/lt/LC_MESSAGES/django.po +8 -8
  437. wagtail/images/locale/nb/LC_MESSAGES/django.po +8 -8
  438. wagtail/images/locale/nl/LC_MESSAGES/django.po +8 -8
  439. wagtail/images/locale/pl/LC_MESSAGES/django.po +11 -11
  440. wagtail/images/locale/pt_BR/LC_MESSAGES/django.po +8 -8
  441. wagtail/images/locale/pt_PT/LC_MESSAGES/django.po +8 -8
  442. wagtail/images/locale/ro/LC_MESSAGES/django.po +8 -8
  443. wagtail/images/locale/ru/LC_MESSAGES/django.po +11 -11
  444. wagtail/images/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  445. wagtail/images/locale/sk_SK/LC_MESSAGES/django.po +23 -8
  446. wagtail/images/locale/sl/LC_MESSAGES/django.mo +0 -0
  447. wagtail/images/locale/sl/LC_MESSAGES/django.po +44 -12
  448. wagtail/images/locale/sv/LC_MESSAGES/django.mo +0 -0
  449. wagtail/images/locale/sv/LC_MESSAGES/django.po +20 -8
  450. wagtail/images/locale/tet/LC_MESSAGES/django.po +4 -4
  451. wagtail/images/locale/th/LC_MESSAGES/django.po +8 -8
  452. wagtail/images/locale/tr/LC_MESSAGES/django.po +6 -6
  453. wagtail/images/locale/tr_TR/LC_MESSAGES/django.po +6 -6
  454. wagtail/images/locale/uk/LC_MESSAGES/django.po +8 -8
  455. wagtail/images/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  456. wagtail/images/locale/zh_Hans/LC_MESSAGES/django.po +49 -5
  457. wagtail/images/locale/zh_Hant/LC_MESSAGES/django.po +4 -4
  458. wagtail/images/models.py +3 -0
  459. wagtail/images/static/wagtailimages/js/image-chooser-modal.js +1 -1
  460. wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
  461. wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
  462. wagtail/images/templates/wagtailimages/images/edit.html +4 -4
  463. wagtail/images/tests/test_admin_views.py +58 -2
  464. wagtail/images/tests/test_image_operations.py +12 -0
  465. wagtail/images/tests/tests.py +27 -2
  466. wagtail/images/views/chooser.py +6 -1
  467. wagtail/images/views/images.py +7 -3
  468. wagtail/images/views/serve.py +1 -0
  469. wagtail/locale/be/LC_MESSAGES/django.po +3 -3
  470. wagtail/locale/en/LC_MESSAGES/django.po +84 -80
  471. wagtail/locale/fa/LC_MESSAGES/django.mo +0 -0
  472. wagtail/locale/fa/LC_MESSAGES/django.po +3 -0
  473. wagtail/locale/fr/LC_MESSAGES/django.mo +0 -0
  474. wagtail/locale/fr/LC_MESSAGES/django.po +23 -4
  475. wagtail/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  476. wagtail/locale/pl/LC_MESSAGES/django.po +3 -3
  477. wagtail/locale/pt_BR/LC_MESSAGES/django.po +1 -1
  478. wagtail/locale/ru/LC_MESSAGES/django.po +3 -3
  479. wagtail/locale/sl/LC_MESSAGES/django.po +2 -2
  480. wagtail/locale/sv/LC_MESSAGES/django.mo +0 -0
  481. wagtail/locale/sv/LC_MESSAGES/django.po +11 -2
  482. wagtail/locales/locale/be/LC_MESSAGES/django.po +3 -3
  483. wagtail/locales/locale/en/LC_MESSAGES/django.po +2 -2
  484. wagtail/locales/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  485. wagtail/locales/locale/pl/LC_MESSAGES/django.po +3 -3
  486. wagtail/locales/locale/ru/LC_MESSAGES/django.po +3 -3
  487. wagtail/locales/locale/sl/LC_MESSAGES/django.po +2 -2
  488. wagtail/locales/tests.py +16 -0
  489. wagtail/locales/wagtail_hooks.py +0 -9
  490. wagtail/migrations/0094_alter_page_locale.py +19 -0
  491. wagtail/models/__init__.py +11 -5
  492. wagtail/models/i18n.py +6 -1
  493. wagtail/project_template/requirements.txt +1 -1
  494. wagtail/search/locale/be/LC_MESSAGES/django.po +3 -3
  495. wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
  496. wagtail/search/locale/fa/LC_MESSAGES/django.mo +0 -0
  497. wagtail/search/locale/fa/LC_MESSAGES/django.po +24 -0
  498. wagtail/search/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  499. wagtail/search/locale/pl/LC_MESSAGES/django.po +3 -3
  500. wagtail/search/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  501. wagtail/search/locale/pt_BR/LC_MESSAGES/django.po +2 -2
  502. wagtail/search/locale/ru/LC_MESSAGES/django.po +3 -3
  503. wagtail/search/locale/sl/LC_MESSAGES/django.po +2 -2
  504. wagtail/search/tests/test_queries.py +24 -0
  505. wagtail/search/utils.py +6 -12
  506. wagtail/signals.py +4 -0
  507. wagtail/sites/locale/be/LC_MESSAGES/django.po +3 -3
  508. wagtail/sites/locale/en/LC_MESSAGES/django.po +2 -2
  509. wagtail/sites/locale/hr_HR/LC_MESSAGES/django.po +2 -2
  510. wagtail/sites/locale/pl/LC_MESSAGES/django.po +3 -3
  511. wagtail/sites/locale/ru/LC_MESSAGES/django.po +3 -3
  512. wagtail/sites/locale/sl/LC_MESSAGES/django.po +2 -2
  513. wagtail/sites/locale/sr/LC_MESSAGES/django.po +2 -2
  514. wagtail/sites/tests.py +15 -0
  515. wagtail/sites/wagtail_hooks.py +0 -9
  516. wagtail/snippets/locale/be/LC_MESSAGES/django.po +3 -3
  517. wagtail/snippets/locale/ca/LC_MESSAGES/django.po +6 -6
  518. wagtail/snippets/locale/de/LC_MESSAGES/django.po +5 -5
  519. wagtail/snippets/locale/en/LC_MESSAGES/django.po +9 -9
  520. wagtail/snippets/locale/es/LC_MESSAGES/django.po +6 -6
  521. wagtail/snippets/locale/fa/LC_MESSAGES/django.mo +0 -0
  522. wagtail/snippets/locale/fa/LC_MESSAGES/django.po +17 -1
  523. wagtail/snippets/locale/fr/LC_MESSAGES/django.po +5 -5
  524. wagtail/snippets/locale/gl/LC_MESSAGES/django.po +6 -6
  525. wagtail/snippets/locale/hr_HR/LC_MESSAGES/django.po +8 -8
  526. wagtail/snippets/locale/hu/LC_MESSAGES/django.po +7 -7
  527. wagtail/snippets/locale/is_IS/LC_MESSAGES/django.po +5 -5
  528. wagtail/snippets/locale/it/LC_MESSAGES/django.po +5 -5
  529. wagtail/snippets/locale/ko/LC_MESSAGES/django.po +6 -6
  530. wagtail/snippets/locale/nb/LC_MESSAGES/django.po +6 -6
  531. wagtail/snippets/locale/nl/LC_MESSAGES/django.po +8 -8
  532. wagtail/snippets/locale/pl/LC_MESSAGES/django.po +9 -9
  533. wagtail/snippets/locale/pt_BR/LC_MESSAGES/django.po +1 -1
  534. wagtail/snippets/locale/ro/LC_MESSAGES/django.po +6 -6
  535. wagtail/snippets/locale/ru/LC_MESSAGES/django.po +8 -8
  536. wagtail/snippets/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  537. wagtail/snippets/locale/sk_SK/LC_MESSAGES/django.po +3 -0
  538. wagtail/snippets/locale/sl/LC_MESSAGES/django.po +8 -8
  539. wagtail/snippets/locale/sr/LC_MESSAGES/django.po +2 -2
  540. wagtail/snippets/locale/sv/LC_MESSAGES/django.po +6 -6
  541. wagtail/snippets/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  542. wagtail/snippets/locale/zh_Hans/LC_MESSAGES/django.po +40 -1
  543. wagtail/snippets/permissions.py +5 -3
  544. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
  545. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
  546. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -1
  547. wagtail/snippets/tests/test_snippets.py +78 -12
  548. wagtail/snippets/tests/test_viewset.py +22 -0
  549. wagtail/snippets/views/snippets.py +19 -14
  550. wagtail/snippets/wagtail_hooks.py +2 -10
  551. wagtail/templatetags/wagtailcore_tags.py +3 -0
  552. wagtail/test/dummy_external_storage.py +1 -1
  553. wagtail/test/i18n/migrations/0003_alter_clusterabletestmodel_locale_and_more.py +40 -0
  554. wagtail/test/routablepage/models.py +4 -0
  555. wagtail/test/snippets/migrations/0012_alter_translatablesnippet_locale.py +20 -0
  556. wagtail/test/testapp/migrations/0038_sociallink.py +52 -0
  557. wagtail/test/testapp/migrations/0039_alter_eventcategory_locale_and_more.py +45 -0
  558. wagtail/test/testapp/models.py +24 -0
  559. wagtail/test/testapp/views.py +1 -0
  560. wagtail/test/testapp/wagtail_hooks.py +9 -0
  561. wagtail/test/urls_multilang.py +6 -1
  562. wagtail/test/urls_multilang_non_root.py +11 -0
  563. wagtail/tests/streamfield_migrations/test_migrations.py +53 -12
  564. wagtail/tests/test_audit_log.py +72 -2
  565. wagtail/tests/test_blocks.py +103 -0
  566. wagtail/tests/test_signals.py +49 -2
  567. wagtail/tests/test_streamfield.py +153 -0
  568. wagtail/tests/test_utils.py +42 -1
  569. wagtail/tests/tests.py +5 -0
  570. wagtail/users/apps.py +1 -0
  571. wagtail/users/forms.py +7 -0
  572. wagtail/users/locale/ar/LC_MESSAGES/django.po +4 -4
  573. wagtail/users/locale/be/LC_MESSAGES/django.po +9 -9
  574. wagtail/users/locale/ca/LC_MESSAGES/django.po +8 -8
  575. wagtail/users/locale/cs/LC_MESSAGES/django.po +6 -6
  576. wagtail/users/locale/cy/LC_MESSAGES/django.po +8 -8
  577. wagtail/users/locale/de/LC_MESSAGES/django.po +8 -8
  578. wagtail/users/locale/el/LC_MESSAGES/django.po +4 -4
  579. wagtail/users/locale/en/LC_MESSAGES/django.po +55 -50
  580. wagtail/users/locale/es/LC_MESSAGES/django.po +8 -8
  581. wagtail/users/locale/et/LC_MESSAGES/django.po +8 -8
  582. wagtail/users/locale/fa/LC_MESSAGES/django.mo +0 -0
  583. wagtail/users/locale/fa/LC_MESSAGES/django.po +69 -7
  584. wagtail/users/locale/fi/LC_MESSAGES/django.po +8 -8
  585. wagtail/users/locale/fr/LC_MESSAGES/django.mo +0 -0
  586. wagtail/users/locale/fr/LC_MESSAGES/django.po +52 -11
  587. wagtail/users/locale/gl/LC_MESSAGES/django.po +8 -8
  588. wagtail/users/locale/hr_HR/LC_MESSAGES/django.po +10 -10
  589. wagtail/users/locale/hu/LC_MESSAGES/django.po +8 -8
  590. wagtail/users/locale/id_ID/LC_MESSAGES/django.po +4 -4
  591. wagtail/users/locale/is_IS/LC_MESSAGES/django.po +8 -8
  592. wagtail/users/locale/it/LC_MESSAGES/django.po +8 -8
  593. wagtail/users/locale/ja/LC_MESSAGES/django.po +4 -4
  594. wagtail/users/locale/ko/LC_MESSAGES/django.po +4 -4
  595. wagtail/users/locale/lt/LC_MESSAGES/django.po +4 -4
  596. wagtail/users/locale/lv/LC_MESSAGES/django.po +4 -4
  597. wagtail/users/locale/mn/LC_MESSAGES/django.po +5 -4
  598. wagtail/users/locale/nb/LC_MESSAGES/django.po +8 -8
  599. wagtail/users/locale/nl/LC_MESSAGES/django.po +6 -6
  600. wagtail/users/locale/pl/LC_MESSAGES/django.po +9 -9
  601. wagtail/users/locale/pt_BR/LC_MESSAGES/django.po +9 -9
  602. wagtail/users/locale/pt_PT/LC_MESSAGES/django.po +8 -8
  603. wagtail/users/locale/ro/LC_MESSAGES/django.po +8 -8
  604. wagtail/users/locale/ru/LC_MESSAGES/django.po +11 -11
  605. wagtail/users/locale/sk_SK/LC_MESSAGES/django.mo +0 -0
  606. wagtail/users/locale/sk_SK/LC_MESSAGES/django.po +12 -5
  607. wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
  608. wagtail/users/locale/sl/LC_MESSAGES/django.po +56 -12
  609. wagtail/users/locale/sv/LC_MESSAGES/django.mo +0 -0
  610. wagtail/users/locale/sv/LC_MESSAGES/django.po +49 -10
  611. wagtail/users/locale/tet/LC_MESSAGES/django.po +4 -4
  612. wagtail/users/locale/th/LC_MESSAGES/django.po +4 -4
  613. wagtail/users/locale/tr/LC_MESSAGES/django.po +4 -4
  614. wagtail/users/locale/tr_TR/LC_MESSAGES/django.po +4 -4
  615. wagtail/users/locale/uk/LC_MESSAGES/django.po +8 -8
  616. wagtail/users/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  617. wagtail/users/locale/zh_Hans/LC_MESSAGES/django.po +49 -5
  618. wagtail/users/locale/zh_Hant/LC_MESSAGES/django.po +2 -2
  619. wagtail/users/models.py +1 -0
  620. wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +3 -2
  621. wagtail/users/templatetags/wagtailusers_tags.py +9 -0
  622. wagtail/users/tests/__init__.py +7 -1
  623. wagtail/users/tests/test_admin_views.py +117 -32
  624. wagtail/users/views/groups.py +4 -0
  625. wagtail/users/views/users.py +58 -14
  626. wagtail/users/wagtail_hooks.py +7 -123
  627. wagtail/utils/utils.py +27 -0
  628. wagtail/utils/version.py +5 -2
  629. wagtail-6.2rc1.dist-info/METADATA +78 -0
  630. {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/RECORD +634 -607
  631. {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/WHEEL +1 -1
  632. wagtail/admin/templates/wagtailadmin/reports/aging_pages.html +0 -58
  633. wagtail/admin/templates/wagtailadmin/reports/page_types_usage.html +0 -18
  634. wagtail/admin/templates/wagtailadmin/reports/site_history.html +0 -57
  635. wagtail/admin/templates/wagtailadmin/reports/workflow.html +0 -81
  636. wagtail/admin/templates/wagtailadmin/reports/workflow_tasks.html +0 -63
  637. wagtail/contrib/frontend_cache/backends.py +0 -400
  638. wagtail/contrib/redirects/templates/wagtailredirects/list.html +0 -43
  639. wagtail/contrib/redirects/templates/wagtailredirects/reports/redirects_report.html +0 -14
  640. wagtail/contrib/redirects/tests/test_reports_view.py +0 -82
  641. wagtail-6.1.2.dist-info/METADATA +0 -78
  642. {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/LICENSE +0 -0
  643. {wagtail-6.1.2.dist-info → wagtail-6.2rc1.dist-info}/entry_points.txt +0 -0
  644. {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(TestCase):
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
- backends.get("cloudfront").purge(
340
- "http://www.wagtail.org/home/events/christmas/"
341
- )
342
- backends.get("cloudfront").purge("http://torchbox.com/blog/")
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 urllib.parse import urlparse, urlunparse
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 = urlparse(url)
83
- new_url = urlunparse(
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
- for backend_name, backend in get_backends(backend_settings, backends).items():
104
- for url in urls:
105
- logger.info("[%s] Purging URL: %s", backend_name, url)
103
+ urls_by_hostname = defaultdict(list)
106
104
 
107
- backend.purge_batch(urls)
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 href="
124
- "\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
123
+ "No redirects have been created. Why not <a "
124
+ "href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
125
125
  msgstr ""
126
- "لم يتم إنشاء عمليات إعادة توجيه. لماذا لا<a href="
127
- "\"%(wagtailredirects_add_redirect_url)s\"> تضيف واحدة</a>؟"
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 && n"
21
- "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
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 href="
68
- "\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
67
+ "No redirects have been created. Why not <a "
68
+ "href=\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
69
69
  msgstr ""
70
- "Няма създадени пренасочвания. Защо не <a href="
71
- "\"%(wagtailredirects_add_redirect_url)s\">добавите един сега</a>?"
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 href="
191
- "\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
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 href="
194
- "\"%(wagtailredirects_add_redirect_url)s\">afegir-ne una</a>?"
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 href="
166
- "\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
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 href="
169
- "\"%(wagtailredirects_add_redirect_url)s\">zde</a>?"
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 \"<em>"
172
- "%(query_string)s</em>\""
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 href="
177
- "\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
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 href="
180
- "\"%(wagtailredirects_add_redirect_url)s\">ychwanegu un</a>?"
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 href="
213
- "\"%(wagtailredirects_add_redirect_url)s\">add one</a>?"
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 href="
216
- "\"%(wagtailredirects_add_redirect_url)s\">Erstellen Sie doch jetzt eine!</a>"
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"