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
@@ -243,16 +243,16 @@ msgstr "Üzgünüm, \"<em>%(query_string)s</em>\" ile eşleşen resim yok"
243
243
 
244
244
  #, python-format
245
245
  msgid ""
246
- "You haven't uploaded any images in this collection. Why not <a href="
247
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
246
+ "You haven't uploaded any images in this collection. Why not <a "
247
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
248
248
  msgstr ""
249
- "Bu koleksiyona resim yüklemediniz. Neden <a href="
250
- "\"%(wagtailimages_add_image_url)s\">şimdi bir tane yüklemiyorsunuz</a>?"
249
+ "Bu koleksiyona resim yüklemediniz. Neden <a "
250
+ "href=\"%(wagtailimages_add_image_url)s\">şimdi bir tane yüklemiyorsunuz</a>?"
251
251
 
252
252
  #, python-format
253
253
  msgid ""
254
- "You haven't uploaded any images. Why not <a href="
255
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
254
+ "You haven't uploaded any images. Why not <a "
255
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
256
256
  msgstr ""
257
257
  "Resim yüklemediniz. Neden <a href=\"%(wagtailimages_add_image_url)s\">şimdi "
258
258
  "bir tane yüklemiyorsunuz</a>?"
@@ -237,16 +237,16 @@ msgstr "Üzgünüm, \"<em>%(query_string)s</em>\" ile eşleşen resim yok"
237
237
 
238
238
  #, python-format
239
239
  msgid ""
240
- "You haven't uploaded any images in this collection. Why not <a href="
241
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
240
+ "You haven't uploaded any images in this collection. Why not <a "
241
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
242
242
  msgstr ""
243
- "Bu koleksiyona resim yüklemediniz. Neden <a href="
244
- "\"%(wagtailimages_add_image_url)s\">şimdi bir tane yüklemiyorsunuz</a>?"
243
+ "Bu koleksiyona resim yüklemediniz. Neden <a "
244
+ "href=\"%(wagtailimages_add_image_url)s\">şimdi bir tane yüklemiyorsunuz</a>?"
245
245
 
246
246
  #, python-format
247
247
  msgid ""
248
- "You haven't uploaded any images. Why not <a href="
249
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
248
+ "You haven't uploaded any images. Why not <a "
249
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
250
250
  msgstr ""
251
251
  "Resim yüklemediniz. Neden <a href=\"%(wagtailimages_add_image_url)s\">şimdi "
252
252
  "bir tane yüklemiyorsunuz</a>?"
@@ -390,19 +390,19 @@ msgstr "Вибачте, жодне зображення не відповіда
390
390
 
391
391
  #, python-format
392
392
  msgid ""
393
- "You haven't uploaded any images in this collection. Why not <a href="
394
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
393
+ "You haven't uploaded any images in this collection. Why not <a "
394
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
395
395
  msgstr ""
396
- "Ви не завантажили жодного зображення до колекції. Чому б <a href="
397
- "\"%(wagtailimages_add_image_url)s\">не завантажити якесь зараз</a>?"
396
+ "Ви не завантажили жодного зображення до колекції. Чому б <a "
397
+ "href=\"%(wagtailimages_add_image_url)s\">не завантажити якесь зараз</a>?"
398
398
 
399
399
  #, python-format
400
400
  msgid ""
401
- "You haven't uploaded any images. Why not <a href="
402
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
401
+ "You haven't uploaded any images. Why not <a "
402
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
403
403
  msgstr ""
404
- "Ви не завантажили жодного зображення. Чому б <a href="
405
- "\"%(wagtailimages_add_image_url)s\">не завантажити якесь зараз</a>?"
404
+ "Ви не завантажили жодного зображення. Чому б <a "
405
+ "href=\"%(wagtailimages_add_image_url)s\">не завантажити якесь зараз</a>?"
406
406
 
407
407
  msgid "Preview"
408
408
  msgstr "Попередній перегляд"
@@ -14,6 +14,7 @@
14
14
  # Matt Westcott <matthew@torchbox.com>, 2022
15
15
  # Vincent Zhao <zhaopu2008@gmail.com>, 2017
16
16
  # Yin Guanhao <sopium@mysterious.site>, 2020-2021
17
+ # Yu Cheng, 2024
17
18
  # 汇民 王 <whuim@qq.com>, 2017-2021
18
19
  msgid ""
19
20
  msgstr ""
@@ -21,7 +22,7 @@ msgstr ""
21
22
  "Report-Msgid-Bugs-To: \n"
22
23
  "POT-Creation-Date: 2024-05-02 10:04+0100\n"
23
24
  "PO-Revision-Date: 2014-02-20 21:05+0000\n"
24
- "Last-Translator: Ford Guo <agile.guo@gmail.com>, 2023\n"
25
+ "Last-Translator: Yu Cheng, 2024\n"
25
26
  "Language-Team: Chinese (China) (http://app.transifex.com/torchbox/wagtail/"
26
27
  "language/zh_CN/)\n"
27
28
  "MIME-Version: 1.0\n"
@@ -47,6 +48,13 @@ msgstr "支持的格式:%(supported_formats)s。"
47
48
  msgid "Not a supported image format. Supported formats: %(supported_formats)s."
48
49
  msgstr "不支持的图片格式。支持类型如下: %(supported_formats)s"
49
50
 
51
+ #, python-format
52
+ msgid ""
53
+ "Not a valid .%(extension)s image. The extension does not match the file "
54
+ "format (%(image_format)s)"
55
+ msgstr ""
56
+ "不是有效的 .%(extension)s 图像。扩展名与文件格式不匹配 (%(image_format)s)"
57
+
50
58
  #, python-format
51
59
  msgid ""
52
60
  "This file is too big (%(file_size)s). Maximum filesize %(max_filesize)s."
@@ -184,6 +192,11 @@ msgstr "是的,添加"
184
192
  msgid "No, don't add"
185
193
  msgstr "否,不添加"
186
194
 
195
+ #, python-format
196
+ msgid "Add 1 image to new collection"
197
+ msgid_plural "Add %(counter)s images to new collection"
198
+ msgstr[0] "将 %(counter)s 张图像添加到新集合"
199
+
187
200
  msgid "Add images to collection"
188
201
  msgstr "将图片添加到集合"
189
202
 
@@ -227,6 +240,13 @@ msgstr "否,不删除"
227
240
  msgid "Popular tags"
228
241
  msgstr "热门标签"
229
242
 
243
+ msgid ""
244
+ "Upload successful. However, your new image seems to be a duplicate of an "
245
+ "existing image. You may delete it if it wasn't required."
246
+ msgstr ""
247
+ "上传成功。但是,您上传的新图像似乎与现有图像重复。如果不需要,您可以将其删"
248
+ "除。"
249
+
230
250
  msgid "Existing"
231
251
  msgstr "已存在"
232
252
 
@@ -246,6 +266,9 @@ msgstr "最新图片"
246
266
  msgid "Select %(title)s"
247
267
  msgstr "选择 %(title)s"
248
268
 
269
+ msgid "You haven't uploaded any images in this collection."
270
+ msgstr "您尚未上传此集合中的任何图片。"
271
+
249
272
  msgid ""
250
273
  "Why not <a class=\"upload-one-now\" href=\"#tab-upload\" data-tab-"
251
274
  "trigger>upload one now</a>?"
@@ -319,6 +342,9 @@ msgstr "未找到文件"
319
342
  msgid "Usage"
320
343
  msgstr "使用情况"
321
344
 
345
+ msgid "Sort by"
346
+ msgstr "排序方式"
347
+
322
348
  msgid "Select all images in listing"
323
349
  msgstr "选择列表中的所有图片"
324
350
 
@@ -328,16 +354,16 @@ msgstr "对不起,没有符合\"<em>%(query_string)s</em>\"的图片。"
328
354
 
329
355
  #, python-format
330
356
  msgid ""
331
- "You haven't uploaded any images in this collection. Why not <a href="
332
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
357
+ "You haven't uploaded any images in this collection. Why not <a "
358
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
333
359
  msgstr ""
334
360
  "此集合中还没有图片。为何不 <a href=\"%(wagtailimages_add_image_url)s\">上传一"
335
361
  "个</a> ?"
336
362
 
337
363
  #, python-format
338
364
  msgid ""
339
- "You haven't uploaded any images. Why not <a href="
340
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
365
+ "You haven't uploaded any images. Why not <a "
366
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
341
367
  msgstr ""
342
368
  "还没上传图片呢。来<a href=\"%(wagtailimages_add_image_url)s\">上传一个</a>吧?"
343
369
 
@@ -347,6 +373,18 @@ msgstr "预览"
347
373
  msgid "URL"
348
374
  msgstr "URL"
349
375
 
376
+ msgid "Image URL"
377
+ msgstr "图片URL"
378
+
379
+ msgid "Copy URL"
380
+ msgstr "复制URL"
381
+
382
+ msgid "Copied to clipboard"
383
+ msgstr "已复制到剪贴板"
384
+
385
+ msgid "Copying to clipboard failed"
386
+ msgstr "复制到剪贴板失败"
387
+
350
388
  msgid "Add multiple images"
351
389
  msgstr "添加多个图片"
352
390
 
@@ -450,6 +488,12 @@ msgstr "标题: (A -> Z)"
450
488
  msgid "Title: (Z -> A)"
451
489
  msgstr "标题: (Z -> A)"
452
490
 
491
+ msgid "File size: (low to high)"
492
+ msgstr "文件大小:(从小到大)"
493
+
494
+ msgid "File size: (high to low)"
495
+ msgstr "文件大小:(从大到小)"
496
+
453
497
  msgid "Images"
454
498
  msgstr "图片"
455
499
 
@@ -223,16 +223,16 @@ msgstr "對不起,沒有符合\"<em>%(query_string)s</em>\"的圖片。"
223
223
 
224
224
  #, python-format
225
225
  msgid ""
226
- "You haven't uploaded any images in this collection. Why not <a href="
227
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
226
+ "You haven't uploaded any images in this collection. Why not <a "
227
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
228
228
  msgstr ""
229
229
  "此集合中還沒有圖片。為何不 <a href=\"%(wagtailimages_add_image_url)s\">上傳一"
230
230
  "個</a> ?"
231
231
 
232
232
  #, python-format
233
233
  msgid ""
234
- "You haven't uploaded any images. Why not <a href="
235
- "\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
234
+ "You haven't uploaded any images. Why not <a "
235
+ "href=\"%(wagtailimages_add_image_url)s\">upload one now</a>?"
236
236
  msgstr ""
237
237
  "還沒上傳圖片呢。來<a href=\"%(wagtailimages_add_image_url)s\">上傳一個</a>吧?"
238
238
 
wagtail/images/models.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import concurrent.futures
2
4
  import hashlib
3
5
  import itertools
@@ -59,6 +61,7 @@ IMAGE_FORMAT_EXTENSIONS = {
59
61
  "gif": ".gif",
60
62
  "webp": ".webp",
61
63
  "svg": ".svg",
64
+ "ico": ".ico",
62
65
  }
63
66
 
64
67
 
@@ -1 +1 @@
1
- (()=>{"use strict";var e,o={3188:(e,o,t)=>{var r=t(1669),a=t.n(r),i=t(2614);class n extends i.C4{ajaxifyLinks(e,o){super.ajaxifyLinks(e,o),a()("a.upload-one-now").on("click",(e=>{const o=a()("#id_collection_id").val();o&&a()("#id_image-chooser-upload-collection").val(o),e.preventDefault()}))}onLoadChooseStep(e){super.onLoadChooseStep(e),a()("a.suggested-tag").on("click",(e=>(a()("#id_q").val(""),this.searchController.search({tag:a()(e.currentTarget).text(),collection_id:a()("#id_collection_id").val()}),!1)))}onLoadDuplicateFoundStep(e,o){a()("#tab-upload",e.body).replaceWith(o.htmlFragment),a()(".use-new-image",e.body).on("click",(o=>(e.loadUrl(o.currentTarget.href),!1))),a()(".use-existing-image",e.body).on("click",(o=>{var t=a()(o.currentTarget).closest("form"),r=a()('input[name="csrfmiddlewaretoken"]',t).val();return e.postForm(o.currentTarget.href,{csrfmiddlewaretoken:r}),!1}))}onLoadSelectFormatStep(e){var o=document.querySelector("#id_image-chooser-insertion-image_is_decorative"),t=document.querySelector("#id_image-chooser-insertion-alt_text"),r=document.querySelector('[for="id_image-chooser-insertion-alt_text"]');function i(){t.setAttribute("disabled","disabled"),r.classList.remove("required")}function n(){t.removeAttribute("disabled"),r.classList.add("required")}o.checked?i():n(),o.addEventListener("change",(e=>{e.target.checked?i():n()})),a()("form",e.body).on("submit",(o=>(a().post(o.currentTarget.action,a()(o.currentTarget).serialize(),e.loadResponseText,"text"),!1)))}getOnLoadHandlers(){const e=super.getOnLoadHandlers();return e.duplicate_found=(e,o)=>{this.onLoadDuplicateFoundStep(e,o)},e.select_format=(e,o)=>{this.onLoadSelectFormatStep(e,o)},e}}window.IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS=new n({creationFormFileFieldSelector:"#id_image-chooser-upload-file",creationFormTitleFieldSelector:"#id_image-chooser-upload-title",creationFormEventName:"wagtail:images-upload",creationFormTabSelector:"#tab-upload"}).getOnLoadHandlers();class l extends i.ZZ{onloadHandlers=window.IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS}window.ImageChooserModal=l},1669:e=>{e.exports=jQuery}},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var i=t[e]={id:e,loaded:!1,exports:{}};return o[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}r.m=o,e=[],r.O=(o,t,a,i)=>{if(!t){var n=1/0;for(s=0;s<e.length;s++){for(var[t,a,i]=e[s],l=!0,d=0;d<t.length;d++)(!1&i||n>=i)&&Object.keys(r.O).every((e=>r.O[e](t[d])))?t.splice(d--,1):(l=!1,i<n&&(n=i));if(l){e.splice(s--,1);var c=a();void 0!==c&&(o=c)}}return o}i=i||0;for(var s=e.length;s>0&&e[s-1][2]>i;s--)e[s]=e[s-1];e[s]=[t,a,i]},r.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return r.d(o,{a:o}),o},r.d=(e,o)=>{for(var t in o)r.o(o,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),r.j=678,(()=>{var e={678:0};r.O.j=o=>0===e[o];var o=(o,t)=>{var a,i,[n,l,d]=t,c=0;if(n.some((o=>0!==e[o]))){for(a in l)r.o(l,a)&&(r.m[a]=l[a]);if(d)var s=d(r)}for(o&&o(t);c<n.length;c++)i=n[c],r.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return r.O(s)},t=globalThis.webpackChunkwagtail=globalThis.webpackChunkwagtail||[];t.forEach(o.bind(null,0)),t.push=o.bind(null,t.push.bind(t))})();var a=r.O(void 0,[321],(()=>r(3188)));a=r.O(a)})();
1
+ (()=>{"use strict";var e,o={3188:(e,o,t)=>{var r=t(1669),a=t.n(r),i=t(2614);class n extends i.C4{ajaxifyLinks(e,o){super.ajaxifyLinks(e,o),a()("a.upload-one-now").on("click",(e=>{const o=a()("#id_collection_id").val();o&&a()("#id_image-chooser-upload-collection").val(o),e.preventDefault()}))}onLoadChooseStep(e){super.onLoadChooseStep(e),a()("a.suggested-tag").on("click",(e=>(a()("#id_q").val(""),this.searchController.search({tag:a()(e.currentTarget).text(),collection_id:a()("#id_collection_id").val()}),!1)))}onLoadDuplicateFoundStep(e,o){a()("#tab-upload",e.body).replaceWith(o.htmlFragment),a()(".use-new-image",e.body).on("click",(o=>(e.loadUrl(o.currentTarget.href),!1))),a()(".use-existing-image",e.body).on("click",(o=>{var t=a()(o.currentTarget).closest("form"),r=a()('input[name="csrfmiddlewaretoken"]',t).val();return e.postForm(o.currentTarget.href,{csrfmiddlewaretoken:r}),!1}))}onLoadSelectFormatStep(e){var o=document.querySelector("#id_image-chooser-insertion-image_is_decorative"),t=document.querySelector("#id_image-chooser-insertion-alt_text"),r=document.querySelector('[for="id_image-chooser-insertion-alt_text"]');function i(){t.setAttribute("disabled","disabled"),r.classList.remove("required")}function n(){t.removeAttribute("disabled"),r.classList.add("required")}o.checked?i():n(),o.addEventListener("change",(e=>{e.target.checked?i():n()})),a()("form",e.body).on("submit",(o=>(a().post(o.currentTarget.action,a()(o.currentTarget).serialize(),e.loadResponseText,"text"),!1)))}getOnLoadHandlers(){const e=super.getOnLoadHandlers();return e.duplicate_found=(e,o)=>{this.onLoadDuplicateFoundStep(e,o)},e.select_format=(e,o)=>{this.onLoadSelectFormatStep(e,o)},e}}window.IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS=new n({creationFormFileFieldSelector:"#id_image-chooser-upload-file",creationFormTitleFieldSelector:"#id_image-chooser-upload-title",creationFormEventName:"wagtail:images-upload",creationFormTabSelector:"#tab-upload"}).getOnLoadHandlers();class l extends i.ZZ{onloadHandlers=window.IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS}window.ImageChooserModal=l},1669:e=>{e.exports=jQuery}},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var i=t[e]={exports:{}};return o[e](i,i.exports,r),i.exports}r.m=o,e=[],r.O=(o,t,a,i)=>{if(!t){var n=1/0;for(s=0;s<e.length;s++){for(var[t,a,i]=e[s],l=!0,d=0;d<t.length;d++)(!1&i||n>=i)&&Object.keys(r.O).every((e=>r.O[e](t[d])))?t.splice(d--,1):(l=!1,i<n&&(n=i));if(l){e.splice(s--,1);var c=a();void 0!==c&&(o=c)}}return o}i=i||0;for(var s=e.length;s>0&&e[s-1][2]>i;s--)e[s]=e[s-1];e[s]=[t,a,i]},r.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return r.d(o,{a:o}),o},r.d=(e,o)=>{for(var t in o)r.o(o,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:o[t]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.j=678,(()=>{var e={678:0};r.O.j=o=>0===e[o];var o=(o,t)=>{var a,i,[n,l,d]=t,c=0;if(n.some((o=>0!==e[o]))){for(a in l)r.o(l,a)&&(r.m[a]=l[a]);if(d)var s=d(r)}for(o&&o(t);c<n.length;c++)i=n[c],r.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return r.O(s)},t=globalThis.webpackChunkwagtail=globalThis.webpackChunkwagtail||[];t.forEach(o.bind(null,0)),t.push=o.bind(null,t.push.bind(t))})();var a=r.O(void 0,[321],(()=>r(3188)));a=r.O(a)})();
@@ -1 +1 @@
1
- (()=>{"use strict";var e,t={7199:(e,t,r)=>{var i=r(9465);class o extends i.y{chooserModalClass=ImageChooserModal;initHTMLElements(e){super.initHTMLElements(e),this.previewImage=this.chooserElement.querySelector("[data-chooser-image]")}getStateFromHTML(){const e=super.getStateFromHTML();return e&&(e.preview={url:this.previewImage.getAttribute("src"),width:this.previewImage.getAttribute("width"),height:this.previewImage.getAttribute("height")}),e}renderState(e){super.renderState(e),this.previewImage.setAttribute("src",e.preview.url),this.previewImage.setAttribute("width",e.preview.width)}}class a extends i._{widgetClass=o;chooserModalClass=ImageChooserModal}window.telepath.register("wagtail.images.widgets.ImageChooser",a)},1669:e=>{e.exports=jQuery}},r={};function i(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={id:e,loaded:!1,exports:{}};return t[e].call(a.exports,a,a.exports,i),a.loaded=!0,a.exports}i.m=t,e=[],i.O=(t,r,o,a)=>{if(!r){var s=1/0;for(h=0;h<e.length;h++){for(var[r,o,a]=e[h],n=!0,l=0;l<r.length;l++)(!1&a||s>=a)&&Object.keys(i.O).every((e=>i.O[e](r[l])))?r.splice(l--,1):(n=!1,a<s&&(s=a));if(n){e.splice(h--,1);var d=o();void 0!==d&&(t=d)}}return t}a=a||0;for(var h=e.length;h>0&&e[h-1][2]>a;h--)e[h]=e[h-1];e[h]=[r,o,a]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),i.j=246,(()=>{var e={246:0};i.O.j=t=>0===e[t];var t=(t,r)=>{var o,a,[s,n,l]=r,d=0;if(s.some((t=>0!==e[t]))){for(o in n)i.o(n,o)&&(i.m[o]=n[o]);if(l)var h=l(i)}for(t&&t(r);d<s.length;d++)a=s[d],i.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return i.O(h)},r=globalThis.webpackChunkwagtail=globalThis.webpackChunkwagtail||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var o=i.O(void 0,[321],(()=>i(7199)));o=i.O(o)})();
1
+ (()=>{"use strict";var e,t={7199:(e,t,r)=>{var i=r(9465);class o extends i.y{chooserModalClass=ImageChooserModal;initHTMLElements(e){super.initHTMLElements(e),this.previewImage=this.chooserElement.querySelector("[data-chooser-image]")}getStateFromHTML(){const e=super.getStateFromHTML();return e&&(e.preview={url:this.previewImage.getAttribute("src"),width:this.previewImage.getAttribute("width"),height:this.previewImage.getAttribute("height")}),e}renderState(e){super.renderState(e),this.previewImage.setAttribute("src",e.preview.url),this.previewImage.setAttribute("width",e.preview.width)}}class a extends i._{widgetClass=o;chooserModalClass=ImageChooserModal}window.telepath.register("wagtail.images.widgets.ImageChooser",a)},1669:e=>{e.exports=jQuery}},r={};function i(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,i),a.exports}i.m=t,e=[],i.O=(t,r,o,a)=>{if(!r){var s=1/0;for(u=0;u<e.length;u++){for(var[r,o,a]=e[u],n=!0,l=0;l<r.length;l++)(!1&a||s>=a)&&Object.keys(i.O).every((e=>i.O[e](r[l])))?r.splice(l--,1):(n=!1,a<s&&(s=a));if(n){e.splice(u--,1);var h=o();void 0!==h&&(t=h)}}return t}a=a||0;for(var u=e.length;u>0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[r,o,a]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.j=246,(()=>{var e={246:0};i.O.j=t=>0===e[t];var t=(t,r)=>{var o,a,[s,n,l]=r,h=0;if(s.some((t=>0!==e[t]))){for(o in n)i.o(n,o)&&(i.m[o]=n[o]);if(l)var u=l(i)}for(t&&t(r);h<s.length;h++)a=s[h],i.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return i.O(u)},r=globalThis.webpackChunkwagtail=globalThis.webpackChunkwagtail||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var o=i.O(void 0,[321],(()=>i(7199)));o=i.O(o)})();
@@ -1 +1 @@
1
- (()=>{"use strict";var e,t={4023:(e,t,r)=>{var i=r(9465);class o extends i.y{chooserModalClass=ImageChooserModal;initHTMLElements(e){super.initHTMLElements(e),this.previewImage=this.chooserElement.querySelector("[data-chooser-image]")}getStateFromHTML(){const e=super.getStateFromHTML();return e&&(e.preview={url:this.previewImage.getAttribute("src"),width:this.previewImage.getAttribute("width"),height:this.previewImage.getAttribute("height")}),e}renderState(e){super.renderState(e),this.previewImage.setAttribute("src",e.preview.url),this.previewImage.setAttribute("width",e.preview.width)}}window.ImageChooser=o},1669:e=>{e.exports=jQuery}},r={};function i(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={id:e,loaded:!1,exports:{}};return t[e].call(a.exports,a,a.exports,i),a.loaded=!0,a.exports}i.m=t,e=[],i.O=(t,r,o,a)=>{if(!r){var n=1/0;for(u=0;u<e.length;u++){for(var[r,o,a]=e[u],s=!0,l=0;l<r.length;l++)(!1&a||n>=a)&&Object.keys(i.O).every((e=>i.O[e](r[l])))?r.splice(l--,1):(s=!1,a<n&&(n=a));if(s){e.splice(u--,1);var h=o();void 0!==h&&(t=h)}}return t}a=a||0;for(var u=e.length;u>0&&e[u-1][2]>a;u--)e[u]=e[u-1];e[u]=[r,o,a]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),i.j=306,(()=>{var e={306:0};i.O.j=t=>0===e[t];var t=(t,r)=>{var o,a,[n,s,l]=r,h=0;if(n.some((t=>0!==e[t]))){for(o in s)i.o(s,o)&&(i.m[o]=s[o]);if(l)var u=l(i)}for(t&&t(r);h<n.length;h++)a=n[h],i.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return i.O(u)},r=globalThis.webpackChunkwagtail=globalThis.webpackChunkwagtail||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var o=i.O(void 0,[321],(()=>i(4023)));o=i.O(o)})();
1
+ (()=>{"use strict";var e,t={4023:(e,t,r)=>{var i=r(9465);class o extends i.y{chooserModalClass=ImageChooserModal;initHTMLElements(e){super.initHTMLElements(e),this.previewImage=this.chooserElement.querySelector("[data-chooser-image]")}getStateFromHTML(){const e=super.getStateFromHTML();return e&&(e.preview={url:this.previewImage.getAttribute("src"),width:this.previewImage.getAttribute("width"),height:this.previewImage.getAttribute("height")}),e}renderState(e){super.renderState(e),this.previewImage.setAttribute("src",e.preview.url),this.previewImage.setAttribute("width",e.preview.width)}}window.ImageChooser=o},1669:e=>{e.exports=jQuery}},r={};function i(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,i),a.exports}i.m=t,e=[],i.O=(t,r,o,a)=>{if(!r){var n=1/0;for(h=0;h<e.length;h++){for(var[r,o,a]=e[h],s=!0,l=0;l<r.length;l++)(!1&a||n>=a)&&Object.keys(i.O).every((e=>i.O[e](r[l])))?r.splice(l--,1):(s=!1,a<n&&(n=a));if(s){e.splice(h--,1);var u=o();void 0!==u&&(t=u)}}return t}a=a||0;for(var h=e.length;h>0&&e[h-1][2]>a;h--)e[h]=e[h-1];e[h]=[r,o,a]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.j=306,(()=>{var e={306:0};i.O.j=t=>0===e[t];var t=(t,r)=>{var o,a,[n,s,l]=r,u=0;if(n.some((t=>0!==e[t]))){for(o in s)i.o(s,o)&&(i.m[o]=s[o]);if(l)var h=l(i)}for(t&&t(r);u<n.length;u++)a=n[u],i.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return i.O(h)},r=globalThis.webpackChunkwagtail=globalThis.webpackChunkwagtail||[];r.forEach(t.bind(null,0)),r.push=t.bind(null,r.push.bind(r))})();var o=i.O(void 0,[321],(()=>i(4023)));o=i.O(o)})();
@@ -51,10 +51,10 @@
51
51
  <div
52
52
  class="focal-point-chooser"
53
53
  style="max-width: {{ rendition.width }}px; max-height: {{ rendition.height }}px;"
54
- data-focal-point-x="{{ image.focal_point_x|default_if_none:'' }}"
55
- data-focal-point-y="{{ image.focal_point_y|default_if_none:'' }}"
56
- data-focal-point-width="{{ image.focal_point_width|default_if_none:'' }}"
57
- data-focal-point-height="{{ image.focal_point_height|default_if_none:'' }}"
54
+ data-focal-point-x="{{ image.focal_point_x|default_if_none:''|unlocalize }}"
55
+ data-focal-point-y="{{ image.focal_point_y|default_if_none:''|unlocalize }}"
56
+ data-focal-point-width="{{ image.focal_point_width|default_if_none:''|unlocalize }}"
57
+ data-focal-point-height="{{ image.focal_point_height|default_if_none:''|unlocalize }}"
58
58
  data-focal-input-label="{% trans 'Image focal point' %}"
59
59
  >
60
60
  <img {{ rendition.attrs }} decoding="async" data-original-width="{{ image.width|unlocalize }}" data-original-height="{{ image.height|unlocalize }}" class="show-transparency">
@@ -1,6 +1,7 @@
1
1
  import datetime
2
2
  import json
3
3
  import urllib
4
+ from unittest.mock import patch
4
5
 
5
6
  from django.conf import settings
6
7
  from django.contrib.auth.models import Group, Permission
@@ -14,6 +15,8 @@ from django.utils.encoding import force_str
14
15
  from django.utils.html import escape, escapejs
15
16
  from django.utils.http import RFC3986_SUBDELIMS, urlencode
16
17
  from django.utils.safestring import mark_safe
18
+ from willow.optimizers.base import OptimizerBase
19
+ from willow.registry import registry
17
20
 
18
21
  from wagtail.admin.admin_url_finder import AdminURLFinder
19
22
  from wagtail.images import get_image_model
@@ -1261,12 +1264,20 @@ class TestImageEditView(WagtailTestUtils, TestCase):
1261
1264
  def test_no_thousand_separators_in_focal_point_editor(self):
1262
1265
  large_image = Image.objects.create(
1263
1266
  title="Test image",
1264
- file=get_test_image_file(size=(1024, 768)),
1267
+ file=get_test_image_file(size=(3840, 2160)),
1268
+ focal_point_x=2048,
1269
+ focal_point_y=1001,
1270
+ focal_point_width=1009,
1271
+ focal_point_height=1002,
1265
1272
  )
1266
1273
  response = self.client.get(
1267
1274
  reverse("wagtailimages:edit", args=(large_image.id,))
1268
1275
  )
1269
- self.assertContains(response, 'data-original-width="1024"')
1276
+ self.assertContains(response, 'data-original-width="3840"')
1277
+ self.assertContains(response, 'data-focal-point-x="2048"')
1278
+ self.assertContains(response, 'data-focal-point-y="1001"')
1279
+ self.assertContains(response, 'data-focal-point-width="1009"')
1280
+ self.assertContains(response, 'data-focal-point-height="1002"')
1270
1281
 
1271
1282
  @override_settings(WAGTAILIMAGES_IMAGE_MODEL="tests.CustomImage")
1272
1283
  def test_unique_together_validation_error(self):
@@ -1681,6 +1692,22 @@ class TestImageChooserView(WagtailTestUtils, TestCase):
1681
1692
  response = self.get({"p": 9999})
1682
1693
  self.assertEqual(response.status_code, 404)
1683
1694
 
1695
+ @override_settings(WAGTAILIMAGES_CHOOSER_PAGE_SIZE=4)
1696
+ def test_chooser_page_size(self):
1697
+ images = [
1698
+ Image(
1699
+ title="Test image %i" % i,
1700
+ file=get_test_image_file(size=(1, 1)),
1701
+ )
1702
+ for i in range(1, 12)
1703
+ ]
1704
+ Image.objects.bulk_create(images)
1705
+
1706
+ response = self.get()
1707
+
1708
+ self.assertContains(response, "Page 1 of 3")
1709
+ self.assertEqual(response.status_code, 200)
1710
+
1684
1711
  def test_filter_by_tag(self):
1685
1712
  for i in range(0, 10):
1686
1713
  image = Image.objects.create(
@@ -3519,6 +3546,35 @@ class TestPreviewView(WagtailTestUtils, TestCase):
3519
3546
  self.assertEqual(response.status_code, 200)
3520
3547
  self.assertEqual(response["Content-Type"], "image/png")
3521
3548
 
3549
+ def test_preview_with_optimizer(self):
3550
+ """
3551
+ Test that preview works with optimizers
3552
+
3553
+ Willow optimizers require
3554
+ """
3555
+
3556
+ class DummyOptimizer(OptimizerBase):
3557
+ library_name = "dummy"
3558
+ image_format = "png"
3559
+
3560
+ @classmethod
3561
+ def check_library(cls):
3562
+ return True
3563
+
3564
+ @classmethod
3565
+ def process(cls, file_path: str):
3566
+ pass
3567
+
3568
+ # Get the image
3569
+ with patch.object(registry, "_registered_optimizers", [DummyOptimizer]):
3570
+ response = self.client.get(
3571
+ reverse("wagtailimages:preview", args=(self.image.id, "fill-800x600"))
3572
+ )
3573
+
3574
+ # Check response
3575
+ self.assertEqual(response.status_code, 200)
3576
+ self.assertEqual(response["Content-Type"], "image/png")
3577
+
3522
3578
  def test_get_invalid_filter_spec(self):
3523
3579
  """
3524
3580
  Test that an invalid filter spec returns a 400 response
@@ -1,4 +1,5 @@
1
1
  from io import BytesIO
2
+ from pathlib import Path
2
3
  from unittest.mock import patch
3
4
 
4
5
  from django.test import TestCase, override_settings
@@ -11,6 +12,7 @@ from wagtail.images.exceptions import (
11
12
  )
12
13
  from wagtail.images.image_operations import TransformOperation
13
14
  from wagtail.images.models import Filter, Image
15
+ from wagtail.images.shortcuts import get_rendition_or_not_found
14
16
  from wagtail.images.tests.utils import (
15
17
  get_test_image_file,
16
18
  get_test_image_file_avif,
@@ -693,6 +695,16 @@ class TestFormatFilter(TestCase):
693
695
 
694
696
  self.assertEqual(out.format_name, "ico")
695
697
 
698
+ def test_ico_rendition(self):
699
+ fil = Filter(spec="width-400|format-ico")
700
+ good_image = Image.objects.create(
701
+ title="Test image",
702
+ file=get_test_image_file(),
703
+ )
704
+
705
+ rendition = get_rendition_or_not_found(good_image, fil)
706
+ self.assertEqual(Path(rendition.file.name).suffix, ".ico")
707
+
696
708
  def test_webp_lossless(self):
697
709
  fil = Filter(spec="width-400|format-webp-lossless")
698
710
  image = Image.objects.create(
@@ -1,6 +1,8 @@
1
1
  import os
2
2
  import unittest
3
+ from io import BytesIO
3
4
 
5
+ import willow
4
6
  from django import forms, template
5
7
  from django.conf import settings
6
8
  from django.core.exceptions import ImproperlyConfigured, ValidationError
@@ -9,6 +11,11 @@ from django.test import TestCase, override_settings
9
11
  from django.test.signals import setting_changed
10
12
  from django.urls import reverse
11
13
  from taggit.forms import TagField, TagWidget
14
+ from willow.image import (
15
+ AvifImageFile,
16
+ PNGImageFile,
17
+ SvgImageFile,
18
+ )
12
19
  from willow.image import ImageFile as WillowImageFile
13
20
 
14
21
  from wagtail.images import get_image_model, get_image_model_string
@@ -359,6 +366,9 @@ class TestFrontendServeView(TestCase):
359
366
  self.assertEqual(response.status_code, 200)
360
367
  self.assertTrue(response.streaming)
361
368
  self.assertEqual(response["Content-Type"], "image/png")
369
+ # Ensure the file can actually be read
370
+ image = willow.Image.open(b"".join(response.streaming_content))
371
+ self.assertIsInstance(image, PNGImageFile)
362
372
 
363
373
  def test_get_svg(self):
364
374
  image = Image.objects.create(title="Test SVG", file=get_test_image_file_svg())
@@ -375,6 +385,9 @@ class TestFrontendServeView(TestCase):
375
385
  self.assertEqual(response.status_code, 200)
376
386
  self.assertTrue(response.streaming)
377
387
  self.assertEqual(response["Content-Type"], "image/svg+xml")
388
+ # Ensure the file can actually be read
389
+ image = willow.Image.open(BytesIO(b"".join(response.streaming_content)))
390
+ self.assertIsInstance(image, SvgImageFile)
378
391
 
379
392
  @override_settings(WAGTAILIMAGES_FORMAT_CONVERSIONS={"avif": "avif"})
380
393
  def test_get_avif(self):
@@ -392,6 +405,9 @@ class TestFrontendServeView(TestCase):
392
405
  self.assertEqual(response.status_code, 200)
393
406
  self.assertTrue(response.streaming)
394
407
  self.assertEqual(response["Content-Type"], "image/avif")
408
+ # Ensure the file can actually be read
409
+ image = willow.Image.open(b"".join(response.streaming_content))
410
+ self.assertIsInstance(image, AvifImageFile)
395
411
 
396
412
  def test_get_with_extra_component(self):
397
413
  """
@@ -412,6 +428,9 @@ class TestFrontendServeView(TestCase):
412
428
  self.assertEqual(response.status_code, 200)
413
429
  self.assertTrue(response.streaming)
414
430
  self.assertEqual(response["Content-Type"], "image/png")
431
+ # Ensure the file can actually be read
432
+ image = willow.Image.open(b"".join(response.streaming_content))
433
+ self.assertIsInstance(image, PNGImageFile)
415
434
 
416
435
  def test_get_with_too_many_extra_components(self):
417
436
  """
@@ -443,6 +462,9 @@ class TestFrontendServeView(TestCase):
443
462
  self.assertEqual(response.status_code, 200)
444
463
  self.assertTrue(response.streaming)
445
464
  self.assertEqual(response["Content-Type"], "image/png")
465
+ # Ensure the file can actually be read
466
+ image = willow.Image.open(b"".join(response.streaming_content))
467
+ self.assertIsInstance(image, PNGImageFile)
446
468
 
447
469
  def test_get_with_redirect_action(self):
448
470
  signature = generate_signature(self.image.id, "fill-800x600")
@@ -472,7 +494,7 @@ class TestFrontendServeView(TestCase):
472
494
 
473
495
  def test_get_with_custom_key(self):
474
496
  """
475
- Test that that the key can be changed on the view
497
+ Test that the key can be changed on the view
476
498
  """
477
499
  # Generate signature
478
500
  signature = generate_signature(self.image.id, "fill-800x600", key="custom")
@@ -488,10 +510,13 @@ class TestFrontendServeView(TestCase):
488
510
 
489
511
  # Check response
490
512
  self.assertEqual(response.status_code, 200)
513
+ # Ensure the file can actually be read
514
+ image = willow.Image.open(b"".join(response.streaming_content))
515
+ self.assertIsInstance(image, PNGImageFile)
491
516
 
492
517
  def test_get_with_custom_key_using_default_key(self):
493
518
  """
494
- Test that that the key can be changed on the view
519
+ Test that the key can be changed on the view
495
520
 
496
521
  This tests that the default key no longer works when the key is changed on the view
497
522
  """
@@ -72,10 +72,15 @@ class ImageCreationFormMixin(CreationFormMixin):
72
72
  class BaseImageChooseView(BaseChooseView):
73
73
  template_name = "wagtailimages/chooser/chooser.html"
74
74
  results_template_name = "wagtailimages/chooser/results.html"
75
- per_page = getattr(settings, "WAGTAILIMAGES_CHOOSER_PAGE_SIZE", 12)
76
75
  ordering = "-created_at"
77
76
  construct_queryset_hook_name = "construct_image_chooser_queryset"
78
77
 
78
+ @property
79
+ def per_page(self):
80
+ # Make per_page into a property so that we can read back WAGTAILIMAGES_CHOOSER_PAGE_SIZE
81
+ # at runtime.
82
+ return getattr(settings, "WAGTAILIMAGES_CHOOSER_PAGE_SIZE", 20)
83
+
79
84
  def get_object_list(self):
80
85
  return (
81
86
  permission_policy.instances_user_has_any_permission_for(
@@ -1,8 +1,9 @@
1
1
  import os
2
+ from tempfile import SpooledTemporaryFile
2
3
 
3
4
  from django.conf import settings
4
5
  from django.core.exceptions import PermissionDenied
5
- from django.http import HttpResponse, JsonResponse
6
+ from django.http import FileResponse, HttpResponse, JsonResponse
6
7
  from django.shortcuts import get_object_or_404, redirect
7
8
  from django.template.response import TemplateResponse
8
9
  from django.urls import reverse
@@ -291,8 +292,11 @@ def preview(request, image_id, filter_spec):
291
292
  image = get_object_or_404(get_image_model(), id=image_id)
292
293
 
293
294
  try:
294
- response = HttpResponse()
295
- image = Filter(spec=filter_spec).run(image, response)
295
+ # Temporary image needs to be an instance that Willow can run optimizers on
296
+ temp_image = SpooledTemporaryFile(max_size=settings.FILE_UPLOAD_MAX_MEMORY_SIZE)
297
+ image = Filter(spec=filter_spec).run(image, temp_image)
298
+ temp_image.seek(0)
299
+ response = FileResponse(temp_image)
296
300
  response["Content-Type"] = "image/" + image.format_name
297
301
  return response
298
302
  except InvalidFilterSpecError:
@@ -65,6 +65,7 @@ class ServeView(View):
65
65
  mime_type = willow_image.mime_type
66
66
 
67
67
  # Serve the file
68
+ rendition.file.open("rb")
68
69
  return FileResponse(rendition.file, content_type=mime_type)
69
70
 
70
71
  def redirect(self, rendition):
@@ -18,9 +18,9 @@ msgstr ""
18
18
  "Content-Type: text/plain; charset=UTF-8\n"
19
19
  "Content-Transfer-Encoding: 8bit\n"
20
20
  "Language: be\n"
21
- "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
22
- "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
23
- "%100>=11 && n%100<=14)? 2 : 3);\n"
21
+ "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
22
+ "n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
23
+ "(n%100>=11 && n%100<=14)? 2 : 3);\n"
24
24
 
25
25
  msgid "Wagtail API v2"
26
26
  msgstr "Wagtail API v2"