wagtail 6.3.1__py3-none-any.whl → 6.4rc1__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 (307) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/actions/publish_revision.py +4 -5
  3. wagtail/admin/auth.py +0 -2
  4. wagtail/admin/checks.py +1 -1
  5. wagtail/admin/filters.py +3 -1
  6. wagtail/admin/forms/account.py +21 -11
  7. wagtail/admin/forms/collections.py +2 -9
  8. wagtail/admin/forms/formsets.py +32 -0
  9. wagtail/admin/forms/pages.py +5 -1
  10. wagtail/admin/forms/workflows.py +2 -13
  11. wagtail/admin/locale/ar/LC_MESSAGES/django.mo +0 -0
  12. wagtail/admin/locale/ar/LC_MESSAGES/django.po +68 -1
  13. wagtail/admin/locale/ar/LC_MESSAGES/djangojs.mo +0 -0
  14. wagtail/admin/locale/ar/LC_MESSAGES/djangojs.po +5 -1
  15. wagtail/admin/locale/en/LC_MESSAGES/django.po +312 -356
  16. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +21 -16
  17. wagtail/admin/locale/gl/LC_MESSAGES/djangojs.mo +0 -0
  18. wagtail/admin/locale/gl/LC_MESSAGES/djangojs.po +5 -5
  19. wagtail/admin/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  20. wagtail/admin/locale/pt_BR/LC_MESSAGES/django.po +29 -0
  21. wagtail/admin/menu.py +0 -13
  22. wagtail/admin/panels/base.py +2 -2
  23. wagtail/admin/panels/group.py +4 -1
  24. wagtail/admin/panels/inline_panel.py +5 -2
  25. wagtail/admin/panels/model_utils.py +36 -0
  26. wagtail/admin/panels/page_utils.py +2 -40
  27. wagtail/admin/panels/signal_handlers.py +0 -2
  28. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  29. wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
  30. wagtail/admin/static/wagtailadmin/css/panels/streamfield.css +1 -1
  31. wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
  32. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  33. wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -8
  34. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  35. wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
  36. wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
  37. wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
  38. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  39. wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
  40. wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
  41. wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
  42. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  43. wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +7 -0
  44. wagtail/admin/templates/wagtailadmin/404.html +4 -0
  45. wagtail/admin/templates/wagtailadmin/chooser/browse.html +2 -1
  46. wagtail/admin/templates/wagtailadmin/chooser/tables/parent_page_cell.html +1 -1
  47. wagtail/admin/templates/wagtailadmin/collections/_privacy_switch.html +8 -1
  48. wagtail/admin/templates/wagtailadmin/generic/confirm_delete.html +15 -9
  49. wagtail/admin/templates/wagtailadmin/generic/confirm_unpublish.html +21 -25
  50. wagtail/admin/templates/wagtailadmin/generic/form.html +1 -1
  51. wagtail/admin/templates/wagtailadmin/generic/preview_error.html +3 -0
  52. wagtail/admin/templates/wagtailadmin/generic/revisions/compare.html +63 -76
  53. wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -2
  54. wagtail/admin/templates/wagtailadmin/pages/edit.html +1 -5
  55. wagtail/admin/templates/wagtailadmin/panels/inline_panel_child.html +1 -0
  56. wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_form.html +1 -1
  57. wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +6 -22
  58. wagtail/admin/templates/wagtailadmin/shared/formatted_field.html +2 -2
  59. wagtail/admin/templates/wagtailadmin/shared/header.html +2 -2
  60. wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +32 -39
  61. wagtail/admin/templates/wagtailadmin/shared/revisions/confirm_unschedule.html +13 -17
  62. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/privacy.html +15 -3
  63. wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +1 -1
  64. wagtail/admin/templates/wagtailadmin/skeleton.html +4 -2
  65. wagtail/admin/templates/wagtailadmin/workflows/create.html +1 -1
  66. wagtail/admin/templates/wagtailadmin/workflows/edit.html +1 -1
  67. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_pages_form.html +1 -1
  68. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_pages_formset.html +6 -23
  69. wagtail/admin/templatetags/wagtailadmin_tags.py +12 -0
  70. wagtail/admin/templatetags/wagtailuserbar.py +2 -3
  71. wagtail/admin/tests/pages/test_create_page.py +110 -1
  72. wagtail/admin/tests/pages/test_edit_page.py +3 -2
  73. wagtail/admin/tests/pages/test_explorer_view.py +18 -0
  74. wagtail/admin/tests/pages/test_page_usage.py +24 -20
  75. wagtail/admin/tests/pages/test_preview.py +69 -1
  76. wagtail/admin/tests/pages/test_revisions.py +40 -6
  77. wagtail/admin/tests/test_account_management.py +39 -1
  78. wagtail/admin/tests/test_audit_log.py +4 -2
  79. wagtail/admin/tests/test_block_preview.py +224 -0
  80. wagtail/admin/tests/test_edit_handlers.py +23 -6
  81. wagtail/admin/tests/test_page_chooser.py +50 -3
  82. wagtail/admin/tests/test_privacy.py +49 -26
  83. wagtail/admin/tests/test_site_summary.py +15 -10
  84. wagtail/admin/tests/test_templatetags.py +19 -0
  85. wagtail/admin/tests/test_userbar.py +82 -1
  86. wagtail/admin/tests/test_views_generic.py +27 -12
  87. wagtail/admin/tests/test_workflows.py +69 -0
  88. wagtail/admin/tests/tests.py +23 -4
  89. wagtail/admin/tests/ui/test_sidebar.py +1 -1
  90. wagtail/admin/tests/viewsets/test_model_viewset.py +15 -13
  91. wagtail/admin/ui/side_panels.py +7 -4
  92. wagtail/admin/urls/__init__.py +6 -0
  93. wagtail/admin/urls/pages.py +1 -1
  94. wagtail/admin/userbar.py +21 -1
  95. wagtail/admin/views/account.py +5 -0
  96. wagtail/admin/views/chooser.py +5 -1
  97. wagtail/admin/views/collections.py +0 -2
  98. wagtail/admin/views/generic/base.py +20 -10
  99. wagtail/admin/views/generic/history.py +0 -1
  100. wagtail/admin/views/generic/models.py +79 -21
  101. wagtail/admin/views/generic/preview.py +50 -1
  102. wagtail/admin/views/mixins.py +4 -2
  103. wagtail/admin/views/pages/bulk_actions/delete.py +11 -23
  104. wagtail/admin/views/pages/bulk_actions/page_bulk_action.py +17 -0
  105. wagtail/admin/views/pages/bulk_actions/publish.py +11 -31
  106. wagtail/admin/views/pages/bulk_actions/unpublish.py +11 -31
  107. wagtail/admin/views/pages/create.py +1 -0
  108. wagtail/admin/views/pages/edit.py +38 -30
  109. wagtail/admin/views/pages/revisions.py +43 -114
  110. wagtail/admin/views/pages/utils.py +0 -1
  111. wagtail/admin/views/tags.py +6 -2
  112. wagtail/admin/views/workflows.py +8 -6
  113. wagtail/admin/viewsets/model.py +0 -4
  114. wagtail/admin/viewsets/pages.py +0 -1
  115. wagtail/admin/widgets/tags.py +1 -0
  116. wagtail/api/v2/tests/test_documents.py +4 -2
  117. wagtail/api/v2/tests/test_images.py +4 -2
  118. wagtail/api/v2/tests/test_pages.py +8 -4
  119. wagtail/blocks/base.py +59 -1
  120. wagtail/blocks/field_block.py +6 -0
  121. wagtail/blocks/list_block.py +4 -0
  122. wagtail/blocks/static_block.py +3 -0
  123. wagtail/blocks/stream_block.py +5 -1
  124. wagtail/blocks/struct_block.py +6 -0
  125. wagtail/compat.py +16 -0
  126. wagtail/contrib/forms/forms.py +27 -7
  127. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +2 -2
  128. wagtail/contrib/forms/locale/gl/LC_MESSAGES/django.mo +0 -0
  129. wagtail/contrib/forms/locale/gl/LC_MESSAGES/django.po +4 -4
  130. wagtail/contrib/forms/tests/test_models.py +7 -5
  131. wagtail/contrib/forms/tests/test_views.py +75 -0
  132. wagtail/contrib/frontend_cache/backends/cloudfront.py +1 -1
  133. wagtail/contrib/frontend_cache/tasks.py +83 -0
  134. wagtail/contrib/frontend_cache/tests.py +48 -33
  135. wagtail/contrib/frontend_cache/utils.py +2 -70
  136. wagtail/contrib/redirects/base_formats.py +2 -2
  137. wagtail/contrib/redirects/locale/ar/LC_MESSAGES/django.mo +0 -0
  138. wagtail/contrib/redirects/locale/ar/LC_MESSAGES/django.po +3 -0
  139. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +24 -37
  140. wagtail/contrib/redirects/templates/wagtailredirects/add.html +1 -24
  141. wagtail/contrib/redirects/templates/wagtailredirects/confirm_delete.html +3 -13
  142. wagtail/contrib/redirects/tests/test_redirects.py +122 -110
  143. wagtail/contrib/redirects/tests/test_signal_handlers.py +75 -69
  144. wagtail/contrib/redirects/urls.py +2 -2
  145. wagtail/contrib/redirects/views.py +35 -73
  146. wagtail/contrib/search_promotions/admin_urls.py +10 -3
  147. wagtail/contrib/search_promotions/forms.py +55 -26
  148. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +44 -54
  149. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +21 -31
  150. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/confirm_delete.html +3 -12
  151. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +11 -34
  152. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotion_form.html +1 -0
  153. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotions_formset.js +2 -1
  154. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/index.html +0 -1
  155. wagtail/contrib/search_promotions/tests.py +814 -13
  156. wagtail/contrib/search_promotions/views/__init__.py +1 -0
  157. wagtail/contrib/search_promotions/views/reports.py +56 -0
  158. wagtail/contrib/search_promotions/views/settings.py +258 -0
  159. wagtail/contrib/search_promotions/wagtail_hooks.py +12 -1
  160. wagtail/contrib/settings/locale/ar/LC_MESSAGES/django.mo +0 -0
  161. wagtail/contrib/settings/locale/ar/LC_MESSAGES/django.po +6 -1
  162. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +3 -3
  163. wagtail/contrib/settings/templates/wagtailsettings/edit.html +1 -5
  164. wagtail/contrib/settings/tests/generic/test_admin.py +2 -5
  165. wagtail/contrib/settings/tests/generic/test_register.py +1 -1
  166. wagtail/contrib/settings/tests/site_specific/test_admin.py +2 -5
  167. wagtail/contrib/settings/tests/site_specific/test_register.py +1 -1
  168. wagtail/contrib/settings/views.py +9 -23
  169. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
  170. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
  171. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  172. wagtail/contrib/table_block/tests.py +4 -1
  173. wagtail/contrib/typed_table_block/blocks.py +3 -0
  174. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
  175. wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
  176. wagtail/contrib/typed_table_block/tests.py +33 -0
  177. wagtail/documents/locale/en/LC_MESSAGES/django.po +26 -26
  178. wagtail/documents/migrations/0011_add_choose_permissions.py +1 -0
  179. wagtail/documents/models.py +1 -0
  180. wagtail/documents/signal_handlers.py +6 -2
  181. wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
  182. wagtail/documents/templates/wagtaildocs/documents/edit.html +1 -3
  183. wagtail/documents/templates/wagtaildocs/multiple/add.html +7 -1
  184. wagtail/documents/tests/test_admin_views.py +74 -33
  185. wagtail/documents/tests/test_views.py +21 -12
  186. wagtail/documents/views/chooser.py +1 -0
  187. wagtail/documents/views/documents.py +1 -2
  188. wagtail/documents/views/multiple.py +0 -1
  189. wagtail/documents/views/serve.py +9 -2
  190. wagtail/documents/wagtail_hooks.py +6 -1
  191. wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
  192. wagtail/embeds/oembed_providers.py +0 -64
  193. wagtail/fields.py +3 -0
  194. wagtail/images/apps.py +2 -1
  195. wagtail/images/blocks.py +14 -2
  196. wagtail/images/forms.py +40 -3
  197. wagtail/images/locale/ar/LC_MESSAGES/django.mo +0 -0
  198. wagtail/images/locale/ar/LC_MESSAGES/django.po +4 -0
  199. wagtail/images/locale/en/LC_MESSAGES/django.po +49 -49
  200. wagtail/images/migrations/0023_add_choose_permissions.py +1 -0
  201. wagtail/images/rich_text/contentstate.py +1 -0
  202. wagtail/images/rich_text/editor_html.py +1 -0
  203. wagtail/images/signal_handlers.py +17 -10
  204. wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
  205. wagtail/images/static/wagtailimages/js/image-block.js +1 -1
  206. wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
  207. wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
  208. wagtail/images/static/wagtailimages/js/image-url-generator.js +1 -1
  209. wagtail/images/static/wagtailimages/js/vendor/jquery.fileupload-image.js +1 -1
  210. wagtail/images/tasks.py +18 -0
  211. wagtail/images/templates/wagtailimages/images/edit.html +1 -3
  212. wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
  213. wagtail/images/templates/wagtailimages/multiple/add.html +7 -2
  214. wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
  215. wagtail/images/tests/test_admin_views.py +53 -29
  216. wagtail/images/tests/test_blocks.py +34 -2
  217. wagtail/images/tests/test_models.py +12 -10
  218. wagtail/images/tests/tests.py +10 -0
  219. wagtail/images/views/chooser.py +1 -0
  220. wagtail/images/views/images.py +1 -3
  221. wagtail/images/views/multiple.py +0 -1
  222. wagtail/images/views/serve.py +18 -2
  223. wagtail/images/widgets.py +3 -0
  224. wagtail/locale/en/LC_MESSAGES/django.po +228 -216
  225. wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
  226. wagtail/management/commands/publish_scheduled.py +1 -1
  227. wagtail/migrations/0087_alter_grouppagepermission_unique_together_and_more.py +16 -8
  228. wagtail/models/__init__.py +300 -119
  229. wagtail/models/i18n.py +2 -2
  230. wagtail/models/panels.py +37 -0
  231. wagtail/models/sites.py +7 -6
  232. wagtail/permission_policies/pages.py +2 -2
  233. wagtail/project_template/project_name/settings/base.py +4 -0
  234. wagtail/project_template/requirements.txt +1 -1
  235. wagtail/query.py +145 -0
  236. wagtail/search/backends/database/mysql/mysql.py +25 -17
  237. wagtail/search/backends/database/postgres/postgres.py +44 -83
  238. wagtail/search/backends/database/sqlite/sqlite.py +25 -17
  239. wagtail/search/backends/elasticsearch7.py +4 -0
  240. wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
  241. wagtail/search/query.py +8 -2
  242. wagtail/search/signal_handlers.py +6 -9
  243. wagtail/search/tasks.py +10 -0
  244. wagtail/search/tests/test_elasticsearch7_backend.py +21 -0
  245. wagtail/search/tests/test_index_functions.py +10 -6
  246. wagtail/search/tests/test_postgres_backend.py +0 -14
  247. wagtail/signal_handlers.py +5 -20
  248. wagtail/sites/locale/en/LC_MESSAGES/django.po +1 -1
  249. wagtail/snippets/locale/en/LC_MESSAGES/django.po +3 -13
  250. wagtail/snippets/locale/sv/LC_MESSAGES/django.mo +0 -0
  251. wagtail/snippets/locale/sv/LC_MESSAGES/django.po +4 -3
  252. wagtail/snippets/tests/test_preview.py +5 -0
  253. wagtail/snippets/tests/test_snippets.py +100 -45
  254. wagtail/snippets/tests/test_usage.py +29 -24
  255. wagtail/snippets/tests/test_viewset.py +1 -1
  256. wagtail/snippets/views/snippets.py +0 -12
  257. wagtail/tasks.py +41 -0
  258. wagtail/templates/wagtailcore/shared/block_preview.html +29 -0
  259. wagtail/test/earlypage/__init__.py +0 -0
  260. wagtail/test/earlypage/migrations/0001_initial.py +37 -0
  261. wagtail/test/earlypage/migrations/__init__.py +0 -0
  262. wagtail/test/earlypage/models.py +14 -0
  263. wagtail/test/settings.py +3 -0
  264. wagtail/test/testapp/fixtures/test.json +7 -0
  265. wagtail/test/testapp/fixtures/test_specific.json +6 -3
  266. wagtail/test/testapp/models.py +58 -44
  267. wagtail/test/testapp/templates/tests/custom_block_preview.html +16 -0
  268. wagtail/test/testapp/templates/tests/static_block_preview.html +5 -0
  269. wagtail/test/testapp/wagtail_hooks.py +9 -0
  270. wagtail/tests/test_blocks.py +189 -2
  271. wagtail/tests/test_hooks.py +166 -1
  272. wagtail/tests/test_management_commands.py +54 -13
  273. wagtail/tests/test_page_allowed_http_methods.py +32 -0
  274. wagtail/tests/test_page_model.py +68 -0
  275. wagtail/tests/test_page_privacy.py +10 -0
  276. wagtail/tests/test_page_queryset.py +79 -0
  277. wagtail/tests/test_reference_index.py +84 -75
  278. wagtail/tests/test_streamfield.py +30 -0
  279. wagtail/tests/test_utils.py +61 -0
  280. wagtail/users/forms.py +2 -9
  281. wagtail/users/locale/en/LC_MESSAGES/django.po +17 -17
  282. wagtail/users/locale/nl/LC_MESSAGES/django.mo +0 -0
  283. wagtail/users/locale/nl/LC_MESSAGES/django.po +4 -3
  284. wagtail/users/templates/wagtailusers/groups/create.html +0 -5
  285. wagtail/users/templates/wagtailusers/groups/includes/page_permissions_form.html +1 -1
  286. wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +6 -6
  287. wagtail/users/tests/test_admin_views.py +96 -4
  288. wagtail/users/tests/test_utils.py +76 -0
  289. wagtail/users/utils.py +43 -11
  290. wagtail/utils/setup.py +2 -2
  291. wagtail/utils/templates.py +26 -0
  292. wagtail/utils/widgets.py +1 -0
  293. wagtail/views.py +9 -1
  294. wagtail/wagtail_hooks.py +67 -29
  295. {wagtail-6.3.1.dist-info → wagtail-6.4rc1.dist-info}/METADATA +2 -2
  296. {wagtail-6.3.1.dist-info → wagtail-6.4rc1.dist-info}/RECORD +300 -287
  297. wagtail/admin/static/wagtailadmin/js/expanding-formset.js +0 -1
  298. wagtail/admin/static/wagtailadmin/js/vendor/rangy-core.js +0 -1
  299. wagtail/admin/static/wagtailadmin/js/vendor/uuidv4.min.js +0 -1
  300. wagtail/contrib/search_promotions/views.py +0 -323
  301. wagtail/images/static/wagtailimages/js/vendor/canvas-to-blob.min.js +0 -1
  302. wagtail/users/static/wagtailusers/js/group-form.js +0 -1
  303. wagtail/users/templates/wagtailusers/groups/includes/group_form_js.html +0 -3
  304. {wagtail-6.3.1.dist-info → wagtail-6.4rc1.dist-info}/LICENSE +0 -0
  305. {wagtail-6.3.1.dist-info → wagtail-6.4rc1.dist-info}/WHEEL +0 -0
  306. {wagtail-6.3.1.dist-info → wagtail-6.4rc1.dist-info}/entry_points.txt +0 -0
  307. {wagtail-6.3.1.dist-info → wagtail-6.4rc1.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ msgid ""
8
8
  msgstr ""
9
9
  "Project-Id-Version: PACKAGE VERSION\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2024-10-21 17:53+0100\n"
11
+ "POT-Creation-Date: 2025-01-20 17:59+0000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -30,7 +30,7 @@ msgstr ""
30
30
  msgid "Date to"
31
31
  msgstr ""
32
32
 
33
- #: forms.py:203
33
+ #: forms.py:221
34
34
  #, python-format
35
35
  msgid ""
36
36
  "There is another field with the label %(label_name)s, please change one of "
@@ -6,14 +6,14 @@
6
6
  # Amós Oviedo <amos.oviedo@gmail.com>, 2016
7
7
  # Amós Oviedo <amos.oviedo@gmail.com>, 2016
8
8
  # Amós Oviedo <amos.oviedo@gmail.com>, 2016
9
- # X Bello <xbello@gmail.com>, 2022
9
+ # X Bello <xbello@gmail.com>, 2022,2024
10
10
  msgid ""
11
11
  msgstr ""
12
12
  "Project-Id-Version: Wagtail\n"
13
13
  "Report-Msgid-Bugs-To: \n"
14
14
  "POT-Creation-Date: 2024-10-21 17:53+0100\n"
15
15
  "PO-Revision-Date: 2014-09-11 15:42+0000\n"
16
- "Last-Translator: X Bello <xbello@gmail.com>, 2022\n"
16
+ "Last-Translator: X Bello <xbello@gmail.com>, 2022,2024\n"
17
17
  "Language-Team: Galician (http://app.transifex.com/torchbox/wagtail/language/"
18
18
  "gl/)\n"
19
19
  "MIME-Version: 1.0\n"
@@ -77,7 +77,7 @@ msgid "Hidden field"
77
77
  msgstr "Campo oculto"
78
78
 
79
79
  msgid "submit time"
80
- msgstr "Hora de envío"
80
+ msgstr "hora de envío"
81
81
 
82
82
  msgid "form submission"
83
83
  msgstr "formulario de envío"
@@ -102,7 +102,7 @@ msgid "field type"
102
102
  msgstr "tipo de campo"
103
103
 
104
104
  msgid "required"
105
- msgstr "obligatorio"
105
+ msgstr "obrigatorio"
106
106
 
107
107
  msgid "choices"
108
108
  msgstr "seleccións"
@@ -603,11 +603,13 @@ class TestFormPageWithCustomFormBuilder(WagtailTestUtils, TestCase):
603
603
  html=True,
604
604
  )
605
605
  # check ip address field has rendered
606
- self.assertContains(
607
- response,
608
- '<input type="text" name="device_ip_address" required id="id_device_ip_address" />',
609
- html=True,
610
- )
606
+ # (not comparing HTML directly because https://docs.djangoproject.com/en/5.1/releases/5.1.5/
607
+ # added a maxlength attribute)
608
+ soup = self.get_soup(response.content)
609
+ input = soup.find("input", {"name": "device_ip_address"})
610
+ self.assertEqual(input["type"], "text")
611
+ self.assertEqual(input["required"], "")
612
+ self.assertEqual(input["id"], "id_device_ip_address")
611
613
 
612
614
  def test_post_invalid_form(self):
613
615
  response = self.client.post(
@@ -1973,6 +1973,52 @@ class TestDuplicateFormFieldLabels(WagtailTestUtils, TestCase):
1973
1973
  text="There is another field with the label Test field, please change one of them.",
1974
1974
  )
1975
1975
 
1976
+ def test_adding_duplicate_form_labels_with_custom_related_name(self):
1977
+ """
1978
+ Ensure duplicate field names are checked, even if a custom related_name is used.
1979
+ ``FormPageWithCustomSubmission`` uses the related_name `custom_form_fields`.
1980
+ """
1981
+
1982
+ post_data = {
1983
+ "title": "Drink selection",
1984
+ "content": "Some content",
1985
+ "slug": "drink-selection",
1986
+ "custom_form_fields-TOTAL_FORMS": "3",
1987
+ "custom_form_fields-INITIAL_FORMS": "3",
1988
+ "custom_form_fields-MIN_NUM_FORMS": "0",
1989
+ "custom_form_fields-MAX_NUM_FORMS": "1000",
1990
+ # Duplicate field labels
1991
+ "custom_form_fields-0-id": "",
1992
+ "custom_form_fields-0-label": "chocolate",
1993
+ "custom_form_fields-0-field_type": "singleline",
1994
+ "custom_form_fields-1-id": "",
1995
+ "custom_form_fields-1-label": "chocolate",
1996
+ "custom_form_fields-1-field_type": "singleline",
1997
+ # Unique field label
1998
+ "custom_form_fields-2-id": "",
1999
+ "custom_form_fields-2-label": "coffee",
2000
+ "custom_form_fields-2-field_type": "singleline",
2001
+ }
2002
+
2003
+ response = self.client.post(
2004
+ reverse(
2005
+ "wagtailadmin_pages:add",
2006
+ args=(
2007
+ "tests",
2008
+ "formpagewithcustomsubmission",
2009
+ self.root_page.id,
2010
+ ),
2011
+ ),
2012
+ post_data,
2013
+ )
2014
+
2015
+ self.assertEqual(response.status_code, 200)
2016
+
2017
+ self.assertContains(
2018
+ response,
2019
+ text="There is another field with the label chocolate, please change one of them.",
2020
+ )
2021
+
1976
2022
 
1977
2023
  class TestPreview(WagtailTestUtils, TestCase):
1978
2024
  post_data = {
@@ -2085,6 +2131,35 @@ class TestFormPageCreate(WagtailTestUtils, TestCase):
2085
2131
  response, reverse("wagtailadmin_pages:edit", args=(page.id,))
2086
2132
  )
2087
2133
 
2134
+ def test_form_page_creation_error_with_custom_clean_method(self):
2135
+ """
2136
+ CustomFormPageSubmission uses a custom `base_form_class` with a clean method
2137
+ that will raise a ValidationError if the from email contains 'example.com'.
2138
+ """
2139
+
2140
+ post_data = {
2141
+ "title": "Drink selection",
2142
+ "slug": "drink-selection",
2143
+ "from_address": "bad@example.com",
2144
+ }
2145
+
2146
+ response = self.client.post(
2147
+ reverse(
2148
+ "wagtailadmin_pages:add",
2149
+ args=("tests", "formpagewithcustomsubmission", self.root_page.id),
2150
+ ),
2151
+ post_data,
2152
+ )
2153
+
2154
+ self.assertEqual(response.status_code, 200)
2155
+
2156
+ self.assertContains(
2157
+ response, "The page could not be created due to validation errors"
2158
+ )
2159
+ self.assertContains(
2160
+ response, "<li>Email cannot be from example.com</li>", count=1
2161
+ )
2162
+
2088
2163
 
2089
2164
  class TestFormPageEdit(WagtailTestUtils, TestCase):
2090
2165
  def setUp(self):
@@ -72,7 +72,7 @@ class CloudfrontBackend(BaseBackend):
72
72
  paths_by_distribution_id[distribution_id].add(url_parsed.path)
73
73
 
74
74
  for distribution_id, paths in paths_by_distribution_id.items():
75
- self._create_invalidation(distribution_id, paths)
75
+ self._create_invalidation(distribution_id, list(paths))
76
76
 
77
77
  def purge(self, url):
78
78
  self.purge_batch([url])
@@ -0,0 +1,83 @@
1
+ import logging
2
+ import re
3
+ from collections import defaultdict
4
+ from urllib.parse import urlsplit, urlunsplit
5
+
6
+ from django.conf import settings
7
+ from django_tasks import task
8
+
9
+ from wagtail.coreutils import get_content_languages
10
+
11
+ from .utils import get_backends
12
+
13
+ logger = logging.getLogger("wagtail.frontendcache")
14
+
15
+
16
+ @task()
17
+ def purge_urls_from_cache_task(urls, backend_settings=None, backends=None):
18
+ if not urls:
19
+ return
20
+
21
+ backends = get_backends(backend_settings, backends)
22
+
23
+ # If no backends are configured, there's nothing to do
24
+ if not backends:
25
+ return
26
+
27
+ # Convert each url to urls one for each managed language (WAGTAILFRONTENDCACHE_LANGUAGES setting).
28
+ # The managed languages are common to all the defined backends.
29
+ # This depends on settings.USE_I18N
30
+ # If WAGTAIL_I18N_ENABLED is True, this defaults to WAGTAIL_CONTENT_LANGUAGES
31
+ wagtail_i18n_enabled = getattr(settings, "WAGTAIL_I18N_ENABLED", False)
32
+ content_languages = get_content_languages() if wagtail_i18n_enabled else {}
33
+ languages = getattr(
34
+ settings, "WAGTAILFRONTENDCACHE_LANGUAGES", list(content_languages.keys())
35
+ )
36
+ if settings.USE_I18N and languages:
37
+ langs_regex = "^/(%s)/" % "|".join(languages)
38
+ new_urls = []
39
+
40
+ # Purge the given url for each managed language
41
+ for isocode in languages:
42
+ for url in urls:
43
+ up = urlsplit(url)
44
+ new_url = urlunsplit(
45
+ (
46
+ up.scheme,
47
+ up.netloc,
48
+ re.sub(langs_regex, "/%s/" % isocode, up.path),
49
+ up.query,
50
+ up.fragment,
51
+ )
52
+ )
53
+
54
+ # Check for best performance. True if re.sub found no match
55
+ # It happens when i18n_patterns was not used in urls.py to serve content for different languages from different URLs
56
+ if new_url in new_urls:
57
+ continue
58
+
59
+ new_urls.append(new_url)
60
+
61
+ urls = new_urls
62
+
63
+ urls_by_hostname = defaultdict(list)
64
+
65
+ for url in urls:
66
+ urls_by_hostname[urlsplit(url).netloc].append(url)
67
+
68
+ for hostname, urls in urls_by_hostname.items():
69
+ backends_for_hostname = {
70
+ backend_name: backend
71
+ for backend_name, backend in backends.items()
72
+ if backend.invalidates_hostname(hostname)
73
+ }
74
+
75
+ if not backends_for_hostname:
76
+ logger.info("Unable to find purge backend for %s", hostname)
77
+ continue
78
+
79
+ for backend_name, backend in backends_for_hostname.items():
80
+ for url in urls:
81
+ logger.info("[%s] Purging URL: %s", backend_name, url)
82
+
83
+ backend.purge_batch(urls)
@@ -360,7 +360,7 @@ class TestBackendConfiguration(SimpleTestCase):
360
360
  backends.get("cloudfront").purge("http://torchbox.com/blog/")
361
361
 
362
362
  _create_invalidation.assert_called_once_with(
363
- "frontend", {"/home/events/christmas/"}
363
+ "frontend", ["/home/events/christmas/"]
364
364
  )
365
365
 
366
366
  self.assertTrue(
@@ -447,32 +447,37 @@ class TestCachePurgingFunctions(TestCase):
447
447
  PURGED_URLS.clear()
448
448
 
449
449
  def test_purge_url_from_cache(self):
450
- purge_url_from_cache("http://localhost/foo")
450
+ with self.captureOnCommitCallbacks(execute=True):
451
+ purge_url_from_cache("http://localhost/foo")
451
452
  self.assertEqual(PURGED_URLS, {"http://localhost/foo"})
452
453
 
453
454
  def test_purge_urls_from_cache(self):
454
- purge_urls_from_cache(["http://localhost/foo", "http://localhost/bar"])
455
+ with self.captureOnCommitCallbacks(execute=True):
456
+ purge_urls_from_cache(["http://localhost/foo", "http://localhost/bar"])
455
457
  self.assertEqual(PURGED_URLS, {"http://localhost/foo", "http://localhost/bar"})
456
458
 
457
459
  def test_purge_page_from_cache(self):
458
- page = EventIndex.objects.get(url_path="/home/events/")
459
- purge_page_from_cache(page)
460
+ with self.captureOnCommitCallbacks(execute=True):
461
+ page = EventIndex.objects.get(url_path="/home/events/")
462
+ purge_page_from_cache(page)
460
463
  self.assertEqual(
461
464
  PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
462
465
  )
463
466
 
464
467
  def test_purge_pages_from_cache(self):
465
- purge_pages_from_cache(EventIndex.objects.all())
468
+ with self.captureOnCommitCallbacks(execute=True):
469
+ purge_pages_from_cache(EventIndex.objects.all())
466
470
  self.assertEqual(
467
471
  PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
468
472
  )
469
473
 
470
474
  def test_purge_batch(self):
471
- batch = PurgeBatch()
472
- page = EventIndex.objects.get(url_path="/home/events/")
473
- batch.add_page(page)
474
- batch.add_url("http://localhost/foo")
475
- batch.purge()
475
+ with self.captureOnCommitCallbacks(execute=True):
476
+ batch = PurgeBatch()
477
+ page = EventIndex.objects.get(url_path="/home/events/")
478
+ batch.add_page(page)
479
+ batch.add_url("http://localhost/foo")
480
+ batch.purge()
476
481
 
477
482
  self.assertEqual(
478
483
  PURGED_URLS,
@@ -493,7 +498,8 @@ class TestCachePurgingFunctions(TestCase):
493
498
  )
494
499
  def test_invalidate_specific_location(self):
495
500
  with self.assertLogs(level="INFO") as log_output:
496
- purge_url_from_cache("http://localhost/foo")
501
+ with self.captureOnCommitCallbacks(execute=True):
502
+ purge_url_from_cache("http://localhost/foo")
497
503
 
498
504
  self.assertEqual(PURGED_URLS, set())
499
505
  self.assertIn(
@@ -501,7 +507,8 @@ class TestCachePurgingFunctions(TestCase):
501
507
  log_output.output[0],
502
508
  )
503
509
 
504
- purge_url_from_cache("http://example.com/foo")
510
+ with self.captureOnCommitCallbacks(execute=True):
511
+ purge_url_from_cache("http://example.com/foo")
505
512
  self.assertEqual(PURGED_URLS, {"http://example.com/foo"})
506
513
 
507
514
 
@@ -520,10 +527,11 @@ class TestCloudflareCachePurgingFunctions(TestCase):
520
527
  PURGED_URLS.clear()
521
528
 
522
529
  def test_cloudflare_purge_batch_chunked(self):
523
- batch = PurgeBatch()
524
- urls = [f"https://localhost/foo{i}" for i in range(1, 65)]
525
- batch.add_urls(urls)
526
- batch.purge()
530
+ with self.captureOnCommitCallbacks(execute=True):
531
+ batch = PurgeBatch()
532
+ urls = [f"https://localhost/foo{i}" for i in range(1, 65)]
533
+ batch.add_urls(urls)
534
+ batch.purge()
527
535
 
528
536
  self.assertCountEqual(PURGED_URLS, set(urls))
529
537
 
@@ -543,24 +551,27 @@ class TestCachePurgingSignals(TestCase):
543
551
  PURGED_URLS.clear()
544
552
 
545
553
  def test_purge_on_publish(self):
546
- page = EventIndex.objects.get(url_path="/home/events/")
547
- page.save_revision().publish()
554
+ with self.captureOnCommitCallbacks(execute=True):
555
+ page = EventIndex.objects.get(url_path="/home/events/")
556
+ page.save_revision().publish()
548
557
  self.assertEqual(
549
558
  PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
550
559
  )
551
560
 
552
561
  def test_purge_on_unpublish(self):
553
- page = EventIndex.objects.get(url_path="/home/events/")
554
- page.unpublish()
562
+ with self.captureOnCommitCallbacks(execute=True):
563
+ page = EventIndex.objects.get(url_path="/home/events/")
564
+ page.unpublish()
555
565
  self.assertEqual(
556
566
  PURGED_URLS, {"http://localhost/events/", "http://localhost/events/past/"}
557
567
  )
558
568
 
559
569
  def test_purge_with_unroutable_page(self):
560
- root = Page.objects.get(url_path="/")
561
- page = EventIndex(title="new top-level page")
562
- root.add_child(instance=page)
563
- page.save_revision().publish()
570
+ with self.captureOnCommitCallbacks(execute=True):
571
+ root = Page.objects.get(url_path="/")
572
+ page = EventIndex(title="new top-level page")
573
+ root.add_child(instance=page)
574
+ page.save_revision().publish()
564
575
  self.assertEqual(PURGED_URLS, set())
565
576
 
566
577
  @override_settings(
@@ -569,8 +580,9 @@ class TestCachePurgingSignals(TestCase):
569
580
  WAGTAILFRONTENDCACHE_LANGUAGES=["en", "fr", "pt-br"],
570
581
  )
571
582
  def test_purge_on_publish_in_multilang_env(self):
572
- page = EventIndex.objects.get(url_path="/home/events/")
573
- page.save_revision().publish()
583
+ with self.captureOnCommitCallbacks(execute=True):
584
+ page = EventIndex.objects.get(url_path="/home/events/")
585
+ page.save_revision().publish()
574
586
 
575
587
  self.assertEqual(
576
588
  PURGED_URLS,
@@ -591,8 +603,9 @@ class TestCachePurgingSignals(TestCase):
591
603
  WAGTAIL_CONTENT_LANGUAGES=[("en", "English"), ("fr", "French")],
592
604
  )
593
605
  def test_purge_on_publish_with_i18n_enabled(self):
594
- page = EventIndex.objects.get(url_path="/home/events/")
595
- page.save_revision().publish()
606
+ with self.captureOnCommitCallbacks(execute=True):
607
+ page = EventIndex.objects.get(url_path="/home/events/")
608
+ page.save_revision().publish()
596
609
 
597
610
  self.assertEqual(
598
611
  PURGED_URLS,
@@ -610,9 +623,10 @@ class TestCachePurgingSignals(TestCase):
610
623
  WAGTAIL_CONTENT_LANGUAGES=[("en", "English"), ("fr", "French")],
611
624
  )
612
625
  def test_purge_on_publish_without_i18n_enabled(self):
613
- # It should ignore WAGTAIL_CONTENT_LANGUAGES as WAGTAIL_I18N_ENABLED isn't set
614
- page = EventIndex.objects.get(url_path="/home/events/")
615
- page.save_revision().publish()
626
+ with self.captureOnCommitCallbacks(execute=True):
627
+ # It should ignore WAGTAIL_CONTENT_LANGUAGES as WAGTAIL_I18N_ENABLED isn't set
628
+ page = EventIndex.objects.get(url_path="/home/events/")
629
+ page.save_revision().publish()
616
630
  self.assertEqual(
617
631
  PURGED_URLS,
618
632
  {"http://localhost/en/events/", "http://localhost/en/events/past/"},
@@ -696,7 +710,8 @@ class TestPurgeBatchClass(TestCase):
696
710
  batch.add_url("http://localhost/events/")
697
711
 
698
712
  with self.assertLogs(level="ERROR") as log_output:
699
- batch.purge(backend_settings=backend_settings)
713
+ with self.captureOnCommitCallbacks(execute=True):
714
+ batch.purge(backend_settings=backend_settings)
700
715
 
701
716
  self.assertIn(
702
717
  "Couldn't purge 'http://localhost/events/' from Cloudflare. HTTPError: 500",
@@ -1,14 +1,9 @@
1
1
  import logging
2
- import re
3
- from collections import defaultdict
4
- from urllib.parse import urlsplit, urlunsplit
5
2
 
6
3
  from django.conf import settings
7
4
  from django.core.exceptions import ImproperlyConfigured
8
5
  from django.utils.module_loading import import_string
9
6
 
10
- from wagtail.coreutils import get_content_languages
11
-
12
7
  logger = logging.getLogger("wagtail.frontendcache")
13
8
 
14
9
 
@@ -64,72 +59,9 @@ def purge_url_from_cache(url, backend_settings=None, backends=None):
64
59
 
65
60
 
66
61
  def purge_urls_from_cache(urls, backend_settings=None, backends=None):
67
- if not urls:
68
- return
69
-
70
- backends = get_backends(backend_settings, backends)
71
-
72
- # If no backends are configured, there's nothing to do
73
- if not backends:
74
- return
75
-
76
- # Convert each url to urls one for each managed language (WAGTAILFRONTENDCACHE_LANGUAGES setting).
77
- # The managed languages are common to all the defined backends.
78
- # This depends on settings.USE_I18N
79
- # If WAGTAIL_I18N_ENABLED is True, this defaults to WAGTAIL_CONTENT_LANGUAGES
80
- wagtail_i18n_enabled = getattr(settings, "WAGTAIL_I18N_ENABLED", False)
81
- content_languages = get_content_languages() if wagtail_i18n_enabled else {}
82
- languages = getattr(
83
- settings, "WAGTAILFRONTENDCACHE_LANGUAGES", list(content_languages.keys())
84
- )
85
- if settings.USE_I18N and languages:
86
- langs_regex = "^/(%s)/" % "|".join(languages)
87
- new_urls = []
88
-
89
- # Purge the given url for each managed language
90
- for isocode in languages:
91
- for url in urls:
92
- up = urlsplit(url)
93
- new_url = urlunsplit(
94
- (
95
- up.scheme,
96
- up.netloc,
97
- re.sub(langs_regex, "/%s/" % isocode, up.path),
98
- up.query,
99
- up.fragment,
100
- )
101
- )
102
-
103
- # Check for best performance. True if re.sub found no match
104
- # It happens when i18n_patterns was not used in urls.py to serve content for different languages from different URLs
105
- if new_url in new_urls:
106
- continue
107
-
108
- new_urls.append(new_url)
109
-
110
- urls = new_urls
111
-
112
- urls_by_hostname = defaultdict(list)
113
-
114
- for url in urls:
115
- urls_by_hostname[urlsplit(url).netloc].append(url)
116
-
117
- for hostname, urls in urls_by_hostname.items():
118
- backends_for_hostname = {
119
- backend_name: backend
120
- for backend_name, backend in backends.items()
121
- if backend.invalidates_hostname(hostname)
122
- }
123
-
124
- if not backends_for_hostname:
125
- logger.info("Unable to find purge backend for %s", hostname)
126
- continue
127
-
128
- for backend_name, backend in backends_for_hostname.items():
129
- for url in urls:
130
- logger.info("[%s] Purging URL: %s", backend_name, url)
62
+ from .tasks import purge_urls_from_cache_task
131
63
 
132
- backend.purge_batch(urls)
64
+ purge_urls_from_cache_task.enqueue(list(urls), backend_settings, backends)
133
65
 
134
66
 
135
67
  def _get_page_cached_urls(page):
@@ -1,8 +1,6 @@
1
1
  import csv
2
2
  from io import BytesIO, StringIO
3
3
 
4
- import openpyxl
5
-
6
4
 
7
5
  class Dataset(list):
8
6
  def __init__(self, rows=(), headers=None):
@@ -66,6 +64,8 @@ class XLSX:
66
64
  """
67
65
  Create dataset from the first sheet of a xlsx workbook.
68
66
  """
67
+ import openpyxl
68
+
69
69
  workbook = openpyxl.load_workbook(BytesIO(data), read_only=True, data_only=True)
70
70
  sheet = workbook.worksheets[0]
71
71
  try:
@@ -99,6 +99,9 @@ msgstr "هل أنت متأكد من أنك تريد حذف إعادة التوج
99
99
  msgid "Yes, delete"
100
100
  msgstr "نعم احذف"
101
101
 
102
+ msgid "Cancel"
103
+ msgstr "إلغاء"
104
+
102
105
  msgid "Preview"
103
106
  msgstr "نظر مقدم"
104
107