wagtail 6.2.2__py3-none-any.whl → 6.3rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/actions/copy_for_translation.py +6 -0
  3. wagtail/actions/publish_revision.py +3 -3
  4. wagtail/admin/action_menu.py +5 -3
  5. wagtail/admin/forms/account.py +1 -1
  6. wagtail/admin/icons.py +2 -6
  7. wagtail/admin/locale/cy/LC_MESSAGES/django.mo +0 -0
  8. wagtail/admin/locale/cy/LC_MESSAGES/django.po +32 -0
  9. wagtail/admin/locale/dv/LC_MESSAGES/django.mo +0 -0
  10. wagtail/admin/locale/dv/LC_MESSAGES/django.po +28 -0
  11. wagtail/admin/locale/en/LC_MESSAGES/django.po +451 -485
  12. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +7 -7
  13. wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
  14. wagtail/admin/locale/sl/LC_MESSAGES/django.po +150 -0
  15. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.mo +0 -0
  16. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +9 -2
  17. wagtail/admin/locale/ug/LC_MESSAGES/django.mo +0 -0
  18. wagtail/admin/locale/ug/LC_MESSAGES/django.po +3250 -196
  19. wagtail/admin/localization.py +12 -2
  20. wagtail/admin/panels/model_utils.py +1 -1
  21. wagtail/admin/site_summary.py +0 -2
  22. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  23. wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
  24. wagtail/admin/static/wagtailadmin/images/email-header.jpg +0 -0
  25. wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
  26. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  27. wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +12 -0
  28. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  29. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  30. wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
  31. wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
  32. wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
  33. wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
  34. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  35. wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
  36. wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
  37. wagtail/admin/staticfiles.py +6 -4
  38. wagtail/admin/templates/wagtailadmin/account/account.html +42 -59
  39. wagtail/admin/templates/wagtailadmin/admin_base.html +0 -28
  40. wagtail/admin/templates/wagtailadmin/bulk_actions/footer.html +1 -1
  41. wagtail/admin/templates/wagtailadmin/chooser/_search_results.html +7 -5
  42. wagtail/admin/templates/wagtailadmin/chooser/tables/page_navigate_to_children_cell.html +1 -1
  43. wagtail/admin/templates/wagtailadmin/generic/chooser/results.html +7 -5
  44. wagtail/admin/templates/wagtailadmin/generic/edit.html +0 -8
  45. wagtail/admin/templates/wagtailadmin/generic/form.html +60 -17
  46. wagtail/admin/templates/wagtailadmin/generic/index.html +17 -0
  47. wagtail/admin/templates/wagtailadmin/generic/index_results.html +9 -35
  48. wagtail/admin/templates/wagtailadmin/generic/inspect.html +2 -21
  49. wagtail/admin/templates/wagtailadmin/generic/listing.html +11 -17
  50. wagtail/admin/templates/wagtailadmin/generic/listing_results.html +19 -1
  51. wagtail/admin/templates/wagtailadmin/home/account_summary.html +26 -0
  52. wagtail/admin/templates/wagtailadmin/home/locked_pages.html +28 -18
  53. wagtail/admin/templates/wagtailadmin/home/recent_edits.html +28 -17
  54. wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +2 -2
  55. wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +35 -13
  56. wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +28 -18
  57. wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +43 -32
  58. wagtail/admin/templates/wagtailadmin/home.html +22 -5
  59. wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
  60. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -11
  61. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu_item.html +1 -6
  62. wagtail/admin/templates/wagtailadmin/pages/action_menu/page_locked.html +1 -1
  63. wagtail/admin/templates/wagtailadmin/pages/action_menu/publish.html +1 -1
  64. wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +1 -1
  65. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_delete.html +12 -6
  66. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html +12 -7
  67. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html +17 -11
  68. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html +15 -9
  69. wagtail/admin/templates/wagtailadmin/pages/confirm_delete.html +9 -9
  70. wagtail/admin/templates/wagtailadmin/pages/confirm_move.html +2 -2
  71. wagtail/admin/templates/wagtailadmin/pages/confirm_unpublish.html +4 -4
  72. wagtail/admin/templates/wagtailadmin/pages/create.html +15 -34
  73. wagtail/admin/templates/wagtailadmin/pages/edit.html +15 -30
  74. wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +6 -0
  75. wagtail/admin/templates/wagtailadmin/pages/explorable_index_results.html +60 -0
  76. wagtail/admin/templates/wagtailadmin/pages/index.html +1 -36
  77. wagtail/admin/templates/wagtailadmin/pages/index_results.html +2 -50
  78. wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +1 -1
  79. wagtail/admin/templates/wagtailadmin/pages/listing/_ordering_cell.html +1 -1
  80. wagtail/admin/templates/wagtailadmin/pages/listing/_page_header_buttons.html +1 -1
  81. wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +3 -3
  82. wagtail/admin/templates/wagtailadmin/pages/listing/_pagination.html +1 -1
  83. wagtail/admin/templates/wagtailadmin/pages/listing.html +24 -0
  84. wagtail/admin/templates/wagtailadmin/pages/search.html +1 -20
  85. wagtail/admin/templates/wagtailadmin/pages/search_results.html +27 -25
  86. wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +0 -1
  87. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +2 -2
  88. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +6 -6
  89. wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +1 -1
  90. wagtail/admin/templates/wagtailadmin/shared/action_menu/menu.html +14 -0
  91. wagtail/admin/templates/wagtailadmin/shared/action_menu/menu_item.html +6 -0
  92. wagtail/admin/templates/wagtailadmin/shared/avatar.html +13 -3
  93. wagtail/admin/templates/wagtailadmin/shared/header.html +0 -5
  94. wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +1 -1
  95. wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +4 -1
  96. wagtail/admin/templates/wagtailadmin/shared/pagination_nav.html +1 -1
  97. wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +1 -1
  98. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/locale.html +1 -1
  99. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +2 -2
  100. wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +94 -52
  101. wagtail/admin/templates/wagtailadmin/{pages/_unsaved_changes_warning.html → shared/unsaved_changes_warning.html} +4 -4
  102. wagtail/admin/templates/wagtailadmin/shared/usage_summary.html +2 -2
  103. wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +1 -7
  104. wagtail/admin/templates/wagtailadmin/shared/workflow_history/listing.html +1 -0
  105. wagtail/admin/templates/wagtailadmin/shared/workflow_history/{list.html → listing_results.html} +33 -35
  106. wagtail/admin/templates/wagtailadmin/tables/references_cell.html +1 -1
  107. wagtail/admin/templates/wagtailadmin/workflows/create.html +11 -36
  108. wagtail/admin/templates/wagtailadmin/workflows/create_task.html +0 -38
  109. wagtail/admin/templates/wagtailadmin/workflows/edit.html +44 -74
  110. wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +27 -66
  111. wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -2
  112. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +4 -4
  113. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +15 -11
  114. wagtail/admin/templates/wagtailadmin/workflows/task_chooser/includes/results.html +7 -5
  115. wagtail/admin/templatetags/wagtailadmin_tags.py +51 -22
  116. wagtail/admin/tests/pages/test_content_type_use_view.py +82 -2
  117. wagtail/admin/tests/pages/test_edit_page.py +70 -0
  118. wagtail/admin/tests/pages/test_explorer_view.py +65 -4
  119. wagtail/admin/tests/pages/test_page_search.py +8 -7
  120. wagtail/admin/tests/pages/test_page_usage.py +3 -1
  121. wagtail/admin/tests/pages/test_preview.py +208 -63
  122. wagtail/admin/tests/pages/test_reorder_page.py +91 -1
  123. wagtail/admin/tests/pages/test_view_draft.py +32 -1
  124. wagtail/admin/tests/pages/test_workflow_history.py +288 -7
  125. wagtail/admin/tests/test_account_management.py +23 -3
  126. wagtail/admin/tests/test_audit_log.py +24 -2
  127. wagtail/admin/tests/test_collections_views.py +17 -5
  128. wagtail/admin/tests/test_dashboard.py +1 -1
  129. wagtail/admin/tests/test_edit_handlers.py +3 -2
  130. wagtail/admin/tests/test_icon_sprite.py +4 -0
  131. wagtail/admin/tests/test_privacy.py +5 -19
  132. wagtail/admin/tests/test_reports_views.py +1 -1
  133. wagtail/admin/tests/test_site_summary.py +3 -3
  134. wagtail/admin/tests/test_templatetags.py +27 -3
  135. wagtail/admin/tests/test_upgrade_notification.py +71 -18
  136. wagtail/admin/tests/test_views.py +2 -2
  137. wagtail/admin/tests/test_views_generic.py +13 -0
  138. wagtail/admin/tests/test_widgets.py +3 -3
  139. wagtail/admin/tests/test_workflows.py +172 -27
  140. wagtail/admin/tests/tests.py +1 -1
  141. wagtail/admin/tests/viewsets/test_model_viewset.py +55 -3
  142. wagtail/admin/ui/side_panels.py +19 -0
  143. wagtail/admin/ui/sidebar.py +4 -3
  144. wagtail/admin/ui/tables/__init__.py +14 -1
  145. wagtail/admin/ui/tables/pages.py +6 -1
  146. wagtail/admin/urls/pages.py +10 -1
  147. wagtail/admin/urls/workflows.py +6 -1
  148. wagtail/admin/views/account.py +5 -1
  149. wagtail/admin/views/collections.py +0 -2
  150. wagtail/admin/views/generic/base.py +118 -1
  151. wagtail/admin/views/generic/history.py +158 -26
  152. wagtail/admin/views/generic/models.py +113 -99
  153. wagtail/admin/views/home.py +24 -9
  154. wagtail/admin/views/page_privacy.py +54 -30
  155. wagtail/admin/views/pages/history.py +11 -4
  156. wagtail/admin/views/pages/listing.py +76 -89
  157. wagtail/admin/views/pages/preview.py +1 -1
  158. wagtail/admin/views/pages/search.py +27 -71
  159. wagtail/admin/views/pages/usage.py +63 -24
  160. wagtail/admin/views/pages/utils.py +4 -3
  161. wagtail/admin/views/reports/base.py +0 -6
  162. wagtail/admin/views/workflows.py +67 -25
  163. wagtail/admin/viewsets/model.py +4 -3
  164. wagtail/admin/widgets/chooser.py +2 -1
  165. wagtail/api/v2/tests/test_pages.py +15 -2
  166. wagtail/blocks/field_block.py +15 -3
  167. wagtail/blocks/static_block.py +3 -0
  168. wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.mo +0 -0
  169. wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.po +29 -1
  170. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +15 -11
  171. wagtail/contrib/forms/templates/wagtailforms/confirm_delete.html +1 -0
  172. wagtail/contrib/forms/templates/wagtailforms/index.html +1 -1
  173. wagtail/contrib/forms/templates/wagtailforms/index_results.html +1 -1
  174. wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +2 -1
  175. wagtail/contrib/forms/templates/wagtailforms/panels/form_responses_panel.html +2 -2
  176. wagtail/contrib/forms/tests/test_views.py +234 -35
  177. wagtail/contrib/forms/utils.py +8 -14
  178. wagtail/contrib/forms/views.py +72 -27
  179. wagtail/contrib/frontend_cache/backends/azure.py +1 -1
  180. wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
  181. wagtail/contrib/frontend_cache/backends/dummy.py +11 -0
  182. wagtail/contrib/frontend_cache/tests.py +31 -37
  183. wagtail/contrib/frontend_cache/utils.py +12 -5
  184. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.mo +0 -0
  185. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +16 -1
  186. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +20 -24
  187. wagtail/contrib/redirects/models.py +16 -1
  188. wagtail/contrib/redirects/signal_handlers.py +18 -3
  189. wagtail/contrib/redirects/templates/wagtailredirects/add.html +5 -16
  190. wagtail/contrib/redirects/templates/wagtailredirects/import_summary.html +1 -1
  191. wagtail/contrib/redirects/tests/test_redirects.py +49 -6
  192. wagtail/contrib/redirects/tests/test_signal_handlers.py +42 -1
  193. wagtail/contrib/redirects/views.py +27 -3
  194. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.mo +0 -0
  195. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +60 -1
  196. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +12 -18
  197. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +5 -8
  198. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +15 -10
  199. wagtail/contrib/search_promotions/tests.py +13 -2
  200. wagtail/contrib/search_promotions/views.py +15 -3
  201. wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.mo +0 -0
  202. wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.po +6 -1
  203. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -10
  204. wagtail/contrib/settings/templates/wagtailsettings/edit.html +12 -45
  205. wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.mo +0 -0
  206. wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.po +13 -1
  207. wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.mo +0 -0
  208. wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.po +3 -0
  209. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +4 -4
  210. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.mo +0 -0
  211. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +5 -2
  212. wagtail/contrib/simple_translation/tests/test_views.py +51 -0
  213. wagtail/contrib/simple_translation/wagtail_hooks.py +16 -11
  214. wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.mo +0 -0
  215. wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.po +5 -1
  216. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
  217. wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
  218. wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.po +27 -1
  219. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  220. wagtail/contrib/typed_table_block/blocks.py +25 -0
  221. wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
  222. wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.po +12 -1
  223. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
  224. wagtail/contrib/typed_table_block/tests.py +24 -1
  225. wagtail/coreutils.py +5 -11
  226. wagtail/documents/admin_urls.py +2 -2
  227. wagtail/documents/locale/cy/LC_MESSAGES/django.mo +0 -0
  228. wagtail/documents/locale/cy/LC_MESSAGES/django.po +10 -0
  229. wagtail/documents/locale/en/LC_MESSAGES/django.po +61 -76
  230. wagtail/documents/migrations/0014_alter_document_file_size.py +18 -0
  231. wagtail/documents/models.py +1 -1
  232. wagtail/documents/rich_text/__init__.py +1 -3
  233. wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
  234. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_tags.html +5 -1
  235. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
  236. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_delete.html +11 -5
  237. wagtail/documents/templates/wagtaildocs/documents/add.html +13 -41
  238. wagtail/documents/templates/wagtaildocs/documents/edit.html +28 -56
  239. wagtail/documents/templates/wagtaildocs/documents/index.html +1 -4
  240. wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +2 -2
  241. wagtail/documents/templates/wagtaildocs/multiple/add.html +36 -41
  242. wagtail/documents/tests/test_admin_views.py +64 -6
  243. wagtail/documents/tests/test_site_summary.py +3 -3
  244. wagtail/documents/views/documents.py +103 -113
  245. wagtail/documents/views/multiple.py +19 -1
  246. wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
  247. wagtail/embeds/oembed_providers.py +9 -19
  248. wagtail/fields.py +43 -27
  249. wagtail/images/admin_urls.py +2 -2
  250. wagtail/images/blocks.py +230 -2
  251. wagtail/images/fields.py +17 -29
  252. wagtail/images/image_operations.py +1 -1
  253. wagtail/images/locale/cy/LC_MESSAGES/django.mo +0 -0
  254. wagtail/images/locale/cy/LC_MESSAGES/django.po +128 -1
  255. wagtail/images/locale/en/LC_MESSAGES/django.po +119 -129
  256. wagtail/images/migrations/0025_alter_image_file_alter_rendition_file.py +36 -43
  257. wagtail/images/migrations/0027_image_description.py +20 -0
  258. wagtail/images/models.py +120 -45
  259. wagtail/images/rich_text/__init__.py +1 -3
  260. wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
  261. wagtail/images/static/wagtailimages/js/image-block.js +1 -0
  262. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_tags.html +5 -1
  263. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
  264. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_delete.html +11 -5
  265. wagtail/images/templates/wagtailimages/chooser/results.html +2 -2
  266. wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +2 -2
  267. wagtail/images/templates/wagtailimages/images/_file_field.html +2 -2
  268. wagtail/images/templates/wagtailimages/images/add.html +13 -31
  269. wagtail/images/templates/wagtailimages/images/edit.html +53 -82
  270. wagtail/images/templates/wagtailimages/images/index.html +1 -4
  271. wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
  272. wagtail/images/templates/wagtailimages/multiple/add.html +40 -47
  273. wagtail/images/templates/wagtailimages/widgets/image.html +5 -0
  274. wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
  275. wagtail/images/tests/test_admin_views.py +70 -10
  276. wagtail/images/tests/test_blocks.py +367 -1
  277. wagtail/images/tests/test_image_operations.py +23 -0
  278. wagtail/images/tests/test_models.py +20 -0
  279. wagtail/images/tests/test_signal_handlers.py +99 -95
  280. wagtail/images/tests/test_site_summary.py +3 -3
  281. wagtail/images/tests/test_templatetags.py +11 -7
  282. wagtail/images/tests/tests.py +4 -0
  283. wagtail/images/views/images.py +103 -104
  284. wagtail/images/views/multiple.py +17 -1
  285. wagtail/locale/cy/LC_MESSAGES/django.mo +0 -0
  286. wagtail/locale/cy/LC_MESSAGES/django.po +3 -0
  287. wagtail/locale/en/LC_MESSAGES/django.po +137 -125
  288. wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
  289. wagtail/locale/sl/LC_MESSAGES/django.po +3 -0
  290. wagtail/locales/locale/en/LC_MESSAGES/django.po +8 -8
  291. wagtail/locales/views.py +4 -1
  292. wagtail/migrations/0089_log_entry_data_json_null_to_object.py +1 -7
  293. wagtail/models/__init__.py +122 -14
  294. wagtail/models/audit_log.py +1 -3
  295. wagtail/models/i18n.py +1 -2
  296. wagtail/project_template/Dockerfile +3 -3
  297. wagtail/project_template/requirements.txt +2 -2
  298. wagtail/query.py +17 -4
  299. wagtail/rich_text/__init__.py +2 -3
  300. wagtail/rich_text/pages.py +2 -4
  301. wagtail/rich_text/rewriters.py +2 -2
  302. wagtail/search/backends/database/mysql/query.py +3 -3
  303. wagtail/search/backends/database/sqlite/query.py +6 -6
  304. wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
  305. wagtail/sites/locale/en/LC_MESSAGES/django.po +6 -6
  306. wagtail/sites/views.py +0 -1
  307. wagtail/snippets/action_menu.py +14 -4
  308. wagtail/snippets/locale/cy/LC_MESSAGES/django.mo +0 -0
  309. wagtail/snippets/locale/cy/LC_MESSAGES/django.po +73 -1
  310. wagtail/snippets/locale/en/LC_MESSAGES/django.po +27 -33
  311. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
  312. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
  313. wagtail/snippets/templates/wagtailsnippets/bulk_actions/confirm_bulk_delete.html +5 -3
  314. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/locked.html +1 -1
  315. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -11
  316. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu_item.html +1 -6
  317. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +1 -1
  318. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +1 -1
  319. wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -18
  320. wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -14
  321. wagtail/snippets/templates/wagtailsnippets/snippets/index.html +2 -5
  322. wagtail/snippets/tests/test_preview.py +193 -61
  323. wagtail/snippets/tests/test_snippets.py +247 -38
  324. wagtail/snippets/tests/test_usage.py +5 -0
  325. wagtail/snippets/tests/test_viewset.py +25 -9
  326. wagtail/snippets/tests/test_workflows.py +232 -19
  327. wagtail/snippets/views/snippets.py +1 -10
  328. wagtail/test/numberformat.py +104 -0
  329. wagtail/test/settings.py +10 -0
  330. wagtail/test/settings_ui.py +2 -0
  331. wagtail/test/testapp/migrations/0010_alter_customimage_file_and_more.py +71 -78
  332. wagtail/test/testapp/migrations/0040_nocreatablesubpagetypespage_nosubpagetypespage.py +54 -0
  333. wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py +17 -0
  334. wagtail/test/testapp/migrations/0042_alter_customdocument_file_size_and_more.py +28 -0
  335. wagtail/test/testapp/migrations/0043_customimage_description.py +41 -0
  336. wagtail/test/testapp/migrations/0044_custompreviewsizesmodel_custompreviewsizespage.py +52 -0
  337. wagtail/test/testapp/migrations/0045_alter_streampage_body.py +52 -0
  338. wagtail/test/testapp/models.py +62 -4
  339. wagtail/test/testapp/rich_text.py +2 -2
  340. wagtail/test/testapp/templates/tests/form_page_landing.html +2 -1
  341. wagtail/test/testapp/urls.py +5 -0
  342. wagtail/test/testapp/views.py +5 -0
  343. wagtail/test/utils/page_tests.py +5 -5
  344. wagtail/test/utils/template_tests.py +2 -2
  345. wagtail/tests/test_blocks.py +15 -0
  346. wagtail/tests/test_page_permissions.py +109 -0
  347. wagtail/tests/test_revision_model.py +27 -0
  348. wagtail/tests/test_signals.py +21 -2
  349. wagtail/tests/test_tests.py +30 -0
  350. wagtail/users/locale/cy/LC_MESSAGES/django.mo +0 -0
  351. wagtail/users/locale/cy/LC_MESSAGES/django.po +118 -1
  352. wagtail/users/locale/dv/LC_MESSAGES/django.mo +0 -0
  353. wagtail/users/locale/dv/LC_MESSAGES/django.po +3 -0
  354. wagtail/users/locale/en/LC_MESSAGES/django.po +89 -113
  355. wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
  356. wagtail/users/locale/sl/LC_MESSAGES/django.po +3 -0
  357. wagtail/users/migrations/0014_userprofile_contrast.py +23 -0
  358. wagtail/users/models.py +11 -0
  359. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_assign_role.html +5 -1
  360. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_delete.html +5 -1
  361. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_set_active_state.html +5 -1
  362. wagtail/users/templates/wagtailusers/groups/create.html +19 -17
  363. wagtail/users/templates/wagtailusers/groups/edit.html +2 -40
  364. wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +1 -62
  365. wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +0 -1
  366. wagtail/users/templates/wagtailusers/users/create.html +46 -50
  367. wagtail/users/templates/wagtailusers/users/edit.html +45 -62
  368. wagtail/users/templates/wagtailusers/users/index.html +1 -4
  369. wagtail/users/templatetags/wagtailusers_tags.py +1 -5
  370. wagtail/users/tests/test_admin_views.py +85 -66
  371. wagtail/users/views/groups.py +4 -1
  372. wagtail/users/views/users.py +2 -0
  373. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/METADATA +6 -6
  374. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/RECORD +378 -367
  375. wagtail/admin/static/wagtailadmin/js/preview-panel.js +0 -2
  376. wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +0 -11
  377. wagtail/admin/templates/wagtailadmin/generic/history_results.html +0 -1
  378. wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +0 -3
  379. wagtail/admin/templates/wagtailadmin/pages/usage_results.html +0 -6
  380. wagtail/admin/templates/wagtailadmin/shared/workflow_history/index.html +0 -17
  381. wagtail/admin/templates/wagtailadmin/shared/workflow_history/results.html +0 -17
  382. wagtail/admin/templates/wagtailadmin/workflows/usage.html +0 -44
  383. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/LICENSE +0 -0
  384. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/WHEEL +0 -0
  385. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/entry_points.txt +0 -0
  386. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,54 @@
1
+ # Generated by Django 4.2.11 on 2024-05-10 12:41
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ("wagtailcore", "0093_uploadedfile"),
10
+ ("tests", "0039_alter_eventcategory_locale_and_more"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name="NoCreatableSubpageTypesPage",
16
+ fields=[
17
+ (
18
+ "page_ptr",
19
+ models.OneToOneField(
20
+ auto_created=True,
21
+ on_delete=django.db.models.deletion.CASCADE,
22
+ parent_link=True,
23
+ primary_key=True,
24
+ serialize=False,
25
+ to="wagtailcore.page",
26
+ ),
27
+ ),
28
+ ],
29
+ options={
30
+ "abstract": False,
31
+ },
32
+ bases=("wagtailcore.page",),
33
+ ),
34
+ migrations.CreateModel(
35
+ name="NoSubpageTypesPage",
36
+ fields=[
37
+ (
38
+ "page_ptr",
39
+ models.OneToOneField(
40
+ auto_created=True,
41
+ on_delete=django.db.models.deletion.CASCADE,
42
+ parent_link=True,
43
+ primary_key=True,
44
+ serialize=False,
45
+ to="wagtailcore.page",
46
+ ),
47
+ ),
48
+ ],
49
+ options={
50
+ "abstract": False,
51
+ },
52
+ bases=("wagtailcore.page",),
53
+ ),
54
+ ]
@@ -0,0 +1,17 @@
1
+ # Generated by Django 5.1 on 2024-09-25 15:35
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("tests", "0040_nocreatablesubpagetypespage_nosubpagetypespage"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterModelOptions(
14
+ name="jsonstreammodel",
15
+ options={"verbose_name": "JSON stream model"},
16
+ ),
17
+ ]
@@ -0,0 +1,28 @@
1
+ # Generated by Django 5.0.9 on 2024-10-09 16:09
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("tests", "0041_alter_jsonstreammodel_options"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name="customdocument",
15
+ name="file_size",
16
+ field=models.PositiveBigIntegerField(editable=False, null=True),
17
+ ),
18
+ migrations.AlterField(
19
+ model_name="customdocumentwithauthor",
20
+ name="file_size",
21
+ field=models.PositiveBigIntegerField(editable=False, null=True),
22
+ ),
23
+ migrations.AlterField(
24
+ model_name="customrestaurantdocument",
25
+ name="file_size",
26
+ field=models.PositiveBigIntegerField(editable=False, null=True),
27
+ ),
28
+ ]
@@ -0,0 +1,41 @@
1
+ # Generated by Django 5.0.7 on 2024-08-06 07:39
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("tests", "0042_alter_customdocument_file_size_and_more"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name="customimage",
15
+ name="description",
16
+ field=models.CharField(
17
+ blank=True, default="", max_length=255, verbose_name="description"
18
+ ),
19
+ ),
20
+ migrations.AddField(
21
+ model_name="customimagefilepath",
22
+ name="description",
23
+ field=models.CharField(
24
+ blank=True, default="", max_length=255, verbose_name="description"
25
+ ),
26
+ ),
27
+ migrations.AddField(
28
+ model_name="customimagewithauthor",
29
+ name="description",
30
+ field=models.CharField(
31
+ blank=True, default="", max_length=255, verbose_name="description"
32
+ ),
33
+ ),
34
+ migrations.AddField(
35
+ model_name="customrestaurantimage",
36
+ name="description",
37
+ field=models.CharField(
38
+ blank=True, default="", max_length=255, verbose_name="description"
39
+ ),
40
+ ),
41
+ ]
@@ -0,0 +1,52 @@
1
+ # Generated by Django 5.0.9 on 2024-10-16 05:17
2
+
3
+ import django.db.models.deletion
4
+ import wagtail.models
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ("tests", "0043_customimage_description"),
12
+ ("wagtailcore", "0094_alter_page_locale"),
13
+ ]
14
+
15
+ operations = [
16
+ migrations.CreateModel(
17
+ name="CustomPreviewSizesModel",
18
+ fields=[
19
+ (
20
+ "id",
21
+ models.AutoField(
22
+ auto_created=True,
23
+ primary_key=True,
24
+ serialize=False,
25
+ verbose_name="ID",
26
+ ),
27
+ ),
28
+ ("text", models.TextField()),
29
+ ],
30
+ bases=(wagtail.models.PreviewableMixin, models.Model),
31
+ ),
32
+ migrations.CreateModel(
33
+ name="CustomPreviewSizesPage",
34
+ fields=[
35
+ (
36
+ "page_ptr",
37
+ models.OneToOneField(
38
+ auto_created=True,
39
+ on_delete=django.db.models.deletion.CASCADE,
40
+ parent_link=True,
41
+ primary_key=True,
42
+ serialize=False,
43
+ to="wagtailcore.page",
44
+ ),
45
+ ),
46
+ ],
47
+ options={
48
+ "abstract": False,
49
+ },
50
+ bases=("wagtailcore.page",),
51
+ ),
52
+ ]
@@ -0,0 +1,52 @@
1
+ # Generated by Django 5.1.1 on 2024-10-11 20:40
2
+
3
+ import wagtail.fields
4
+ from django.db import migrations
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ("tests", "0044_custompreviewsizesmodel_custompreviewsizespage"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AlterField(
15
+ model_name="streampage",
16
+ name="body",
17
+ field=wagtail.fields.StreamField(
18
+ [
19
+ ("text", 0),
20
+ ("rich_text", 1),
21
+ ("image", 2),
22
+ ("product", 3),
23
+ ("raw_html", 4),
24
+ ("books", 5),
25
+ ("title_list", 6),
26
+ ("image_with_alt", 7),
27
+ ],
28
+ block_lookup={
29
+ 0: ("wagtail.blocks.CharBlock", (), {}),
30
+ 1: ("wagtail.blocks.RichTextBlock", (), {}),
31
+ 2: (
32
+ "wagtail.test.testapp.models.ExtendedImageChooserBlock",
33
+ (),
34
+ {},
35
+ ),
36
+ 3: (
37
+ "wagtail.blocks.StructBlock",
38
+ [[("name", 0), ("price", 0)]],
39
+ {},
40
+ ),
41
+ 4: ("wagtail.blocks.RawHTMLBlock", (), {}),
42
+ 5: (
43
+ "wagtail.blocks.StreamBlock",
44
+ [[("title", 0), ("author", 0)]],
45
+ {},
46
+ ),
47
+ 6: ("wagtail.blocks.ListBlock", (0,), {}),
48
+ 7: ("wagtail.images.blocks.ImageBlock", [], {}),
49
+ },
50
+ ),
51
+ ),
52
+ ]
@@ -65,7 +65,7 @@ from wagtail.documents.blocks import DocumentChooserBlock
65
65
  from wagtail.documents.models import AbstractDocument, Document
66
66
  from wagtail.fields import RichTextField, StreamField
67
67
  from wagtail.images import get_image_model
68
- from wagtail.images.blocks import ImageChooserBlock
68
+ from wagtail.images.blocks import ImageBlock, ImageChooserBlock
69
69
  from wagtail.images.models import AbstractImage, AbstractRendition, Image
70
70
  from wagtail.models import (
71
71
  DraftStateMixin,
@@ -100,6 +100,21 @@ COMMON_PANELS = (
100
100
  FieldPanel("search_description"),
101
101
  )
102
102
 
103
+ CUSTOM_PREVIEW_SIZES = [
104
+ {
105
+ "name": "custom-mobile",
106
+ "icon": "mobile-alt",
107
+ "device_width": 412,
108
+ "label": "Custom mobile preview",
109
+ },
110
+ {
111
+ "name": "desktop",
112
+ "icon": "desktop",
113
+ "device_width": 1280,
114
+ "label": "Original desktop",
115
+ },
116
+ ]
117
+
103
118
 
104
119
  # Link fields
105
120
 
@@ -195,7 +210,11 @@ class SimplePage(Page):
195
210
 
196
211
 
197
212
  class MultiPreviewModesPage(Page):
198
- template = "tests/simple_page.html"
213
+ preview_templates = {
214
+ "original": "tests/simple_page.html",
215
+ "alt#1": "tests/simple_page_alt.html",
216
+ }
217
+ template = preview_templates["original"]
199
218
 
200
219
  @property
201
220
  def preview_modes(self):
@@ -206,11 +225,23 @@ class MultiPreviewModesPage(Page):
206
225
  return "alt#1"
207
226
 
208
227
  def get_preview_template(self, request, mode_name):
209
- if mode_name == "alt#1":
210
- return "tests/simple_page_alt.html"
228
+ if mode_name in self.preview_templates:
229
+ return self.preview_templates[mode_name]
211
230
  return super().get_preview_template(request, mode_name)
212
231
 
213
232
 
233
+ class CustomPreviewSizesPage(Page):
234
+ template = "tests/simple_page.html"
235
+
236
+ @property
237
+ def preview_sizes(self):
238
+ return CUSTOM_PREVIEW_SIZES
239
+
240
+ @property
241
+ def default_preview_size(self):
242
+ return "desktop"
243
+
244
+
214
245
  # Page with Excluded Fields when copied
215
246
  class PageWithExcludedCopyField(Page):
216
247
  content = models.TextField()
@@ -1079,6 +1110,21 @@ class PreviewableModel(PreviewableMixin, ClusterableModel):
1079
1110
  register_snippet(PreviewableModel)
1080
1111
 
1081
1112
 
1113
+ class CustomPreviewSizesModel(PreviewableMixin, models.Model):
1114
+ text = models.TextField()
1115
+
1116
+ @property
1117
+ def preview_sizes(self):
1118
+ return CUSTOM_PREVIEW_SIZES
1119
+
1120
+ @property
1121
+ def default_preview_size(self):
1122
+ return "desktop"
1123
+
1124
+
1125
+ register_snippet(CustomPreviewSizesModel)
1126
+
1127
+
1082
1128
  class MultiPreviewModesModel(PreviewableMixin, RevisionMixin, models.Model):
1083
1129
  text = models.TextField()
1084
1130
 
@@ -1524,6 +1570,9 @@ class JSONStreamModel(models.Model):
1524
1570
  ],
1525
1571
  )
1526
1572
 
1573
+ class Meta:
1574
+ verbose_name = "JSON stream model"
1575
+
1527
1576
 
1528
1577
  class JSONMinMaxCountStreamModel(models.Model):
1529
1578
  body = StreamField(
@@ -1597,6 +1646,7 @@ class StreamPage(Page):
1597
1646
  "title_list",
1598
1647
  ListBlock(CharBlock()),
1599
1648
  ),
1649
+ ("image_with_alt", ImageBlock()),
1600
1650
  ],
1601
1651
  )
1602
1652
 
@@ -1668,6 +1718,14 @@ class MTIChildPage(MTIBasePage):
1668
1718
  pass
1669
1719
 
1670
1720
 
1721
+ class NoCreatableSubpageTypesPage(Page):
1722
+ subpage_types = [MTIBasePage]
1723
+
1724
+
1725
+ class NoSubpageTypesPage(Page):
1726
+ subpage_types = []
1727
+
1728
+
1671
1729
  class AbstractPage(Page):
1672
1730
  class Meta:
1673
1731
  abstract = True
@@ -7,7 +7,7 @@ class CustomRichTextArea(widgets.Textarea):
7
7
  # mock rendering for individual custom widget
8
8
 
9
9
  return mark_safe(
10
- '<template data-controller="custom-editor" data-id="{0}">{1}</template>'.format(
10
+ '<template data-controller="custom-editor" data-id="{}">{}</template>'.format(
11
11
  attrs["id"],
12
12
  super().render(name, value, attrs),
13
13
  )
@@ -22,7 +22,7 @@ class LegacyRichTextArea(widgets.Textarea):
22
22
  def render(self, name, value, attrs=None, renderer=None):
23
23
  # mock rendering for individual custom widget
24
24
  return mark_safe(
25
- '<template data-controller="legacy-editor" data-id="{0}">{1}</template>'.format(
25
+ '<template data-controller="legacy-editor" data-id="{}">{}</template>'.format(
26
26
  attrs["id"],
27
27
  super().render(name, value, attrs),
28
28
  )
@@ -1,4 +1,5 @@
1
1
  {% extends "tests/base.html" %}
2
+ {% load l10n %}
2
3
 
3
4
  {% block content %}
4
5
  <p>{{ greeting }}</p>
@@ -6,7 +7,7 @@
6
7
 
7
8
  <ul>
8
9
  {% for key, value in form_submission.get_data.items %}
9
- <li>{{ key }}: {{ value }}</li>
10
+ <li>{{ key }}: {{ value|unlocalize }}</li>
10
11
  {% endfor %}
11
12
  </ul>
12
13
  {% endblock %}
@@ -14,4 +14,9 @@ urlpatterns = [
14
14
  views.TestDeleteView.as_view(),
15
15
  name="testapp_generic_delete",
16
16
  ),
17
+ path(
18
+ "test-index-without-model/",
19
+ views.TestIndexViewWithoutModel.as_view(),
20
+ name="testapp_generic_index_without_model",
21
+ ),
17
22
  ]
@@ -68,6 +68,11 @@ class TestIndexView(IndexView):
68
68
  context_object_name = "test_object"
69
69
 
70
70
 
71
+ class TestIndexViewWithoutModel(IndexView):
72
+ def get_base_queryset(self):
73
+ return ModelWithStringTypePrimaryKey.objects.all()
74
+
75
+
71
76
  class CustomModelEditForm(forms.ModelForm):
72
77
  class Meta:
73
78
  model = ModelWithStringTypePrimaryKey
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, Optional
1
+ from typing import Any, Optional
2
2
  from unittest import mock
3
3
 
4
4
  from django.conf import settings
@@ -217,8 +217,8 @@ class WagtailPageTestCase(WagtailTestUtils, TestCase):
217
217
  self,
218
218
  page: Page,
219
219
  route_path: Optional[str] = "/",
220
- query_data: Optional[Dict[str, Any]] = None,
221
- post_data: Optional[Dict[str, Any]] = None,
220
+ query_data: Optional[dict[str, Any]] = None,
221
+ post_data: Optional[dict[str, Any]] = None,
222
222
  user: Optional[AbstractBaseUser] = None,
223
223
  accept_404: Optional[bool] = False,
224
224
  accept_redirect: Optional[bool] = False,
@@ -297,7 +297,7 @@ class WagtailPageTestCase(WagtailTestUtils, TestCase):
297
297
  def assertPageIsEditable(
298
298
  self,
299
299
  page: Page,
300
- post_data: Optional[Dict[str, Any]] = None,
300
+ post_data: Optional[dict[str, Any]] = None,
301
301
  user: Optional[AbstractBaseUser] = None,
302
302
  msg: Optional[str] = None,
303
303
  ):
@@ -379,7 +379,7 @@ class WagtailPageTestCase(WagtailTestUtils, TestCase):
379
379
  self,
380
380
  page: Page,
381
381
  mode: Optional[str] = "",
382
- post_data: Optional[Dict[str, Any]] = None,
382
+ post_data: Optional[dict[str, Any]] = None,
383
383
  user: Optional[AbstractBaseUser] = None,
384
384
  msg: Optional[str] = None,
385
385
  ):
@@ -1,4 +1,4 @@
1
- from typing import Dict, List, Union
1
+ from typing import Union
2
2
 
3
3
  from django.test import SimpleTestCase
4
4
 
@@ -10,7 +10,7 @@ class AdminTemplateTestUtils:
10
10
 
11
11
  def assertBreadcrumbsItemsRendered(
12
12
  self: Union[WagtailTestUtils, SimpleTestCase],
13
- items: List[Dict[str, str]],
13
+ items: list[dict[str, str]],
14
14
  html: Union[str, bytes],
15
15
  ):
16
16
  soup = self.get_soup(html)
@@ -4889,6 +4889,16 @@ class TestPageChooserBlock(TestCase):
4889
4889
 
4890
4890
  self.assertSequenceEqual(pages, expected_pages)
4891
4891
 
4892
+ def test_bulk_to_python_distinct_instances(self):
4893
+ page_ids = [2, 2]
4894
+ block = blocks.PageChooserBlock()
4895
+
4896
+ with self.assertNumQueries(1):
4897
+ pages = block.bulk_to_python(page_ids)
4898
+
4899
+ # Ensure that the two retrieved pages are distinct instances
4900
+ self.assertIsNot(pages[0], pages[1])
4901
+
4892
4902
  def test_extract_references(self):
4893
4903
  block = blocks.PageChooserBlock()
4894
4904
  christmas_page = Page.objects.get(slug="christmas")
@@ -5015,6 +5025,11 @@ class TestStaticBlock(unittest.TestCase):
5015
5025
  result = block.render(None)
5016
5026
  self.assertEqual(result, "<p>PostsStaticBlock template</p>")
5017
5027
 
5028
+ def test_render_without_template(self):
5029
+ block = blocks.StaticBlock()
5030
+ result = block.render(None)
5031
+ self.assertEqual(result, "")
5032
+
5018
5033
  def test_serialize(self):
5019
5034
  block = blocks.StaticBlock()
5020
5035
  result = block.get_prep_value(None)