wagtail 7.1.2__py3-none-any.whl → 7.2rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wagtail/__init__.py +1 -1
- wagtail/actions/copy_page.py +1 -1
- wagtail/actions/create_alias.py +1 -1
- wagtail/actions/delete_page.py +1 -1
- wagtail/actions/publish_page_revision.py +1 -1
- wagtail/actions/publish_revision.py +1 -1
- wagtail/actions/revert_to_page_revision.py +1 -1
- wagtail/actions/unpublish.py +1 -1
- wagtail/actions/unpublish_page.py +1 -1
- wagtail/admin/auth.py +3 -1
- wagtail/admin/checks.py +2 -2
- wagtail/admin/filters.py +28 -1
- wagtail/admin/forms/collections.py +1 -1
- wagtail/admin/forms/comments.py +1 -1
- wagtail/admin/forms/models.py +1 -1
- wagtail/admin/forms/pages.py +1 -1
- wagtail/admin/forms/tags.py +1 -1
- wagtail/admin/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/cs/LC_MESSAGES/django.po +25 -1
- wagtail/admin/locale/en/LC_MESSAGES/django.po +278 -192
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +29 -15
- wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/django.po +3 -2
- wagtail/admin/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/nl/LC_MESSAGES/django.po +57 -3
- wagtail/admin/locale/nl/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/nl/LC_MESSAGES/djangojs.po +8 -2
- wagtail/admin/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ru/LC_MESSAGES/django.po +58 -1
- wagtail/admin/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/tr/LC_MESSAGES/django.po +3 -2
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/chooser-widget.js +1 -1
- wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +2 -2
- wagtail/admin/static/wagtailadmin/js/date-time-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/filtered-select.js +1 -1
- wagtail/admin/static/wagtailadmin/js/icons.js +1 -1
- wagtail/admin/static/wagtailadmin/js/modal-workflow.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser-telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/page-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/task-chooser.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +2 -2
- wagtail/admin/static/wagtailadmin/js/vendor/bootstrap-modal.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/bootstrap-transition.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery-3.6.0.min.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery-ui-1.13.2.min.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.datetimepicker.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.fileupload-process.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.fileupload.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/jquery.iframe-transport.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor/tag-it.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/templates/wagtailadmin/account/account.html +2 -0
- wagtail/admin/templates/wagtailadmin/base.html +14 -0
- wagtail/admin/templates/wagtailadmin/generic/chooser/chooser.html +2 -1
- wagtail/admin/templates/wagtailadmin/generic/chooser/creation_form.html +2 -1
- wagtail/admin/templates/wagtailadmin/panels/multi_field_panel_child.html +1 -1
- wagtail/admin/templates/wagtailadmin/panels/object_list.html +1 -1
- wagtail/admin/templates/wagtailadmin/panels/tabbed_interface.html +3 -2
- wagtail/admin/templates/wagtailadmin/shared/formatted_field.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/forms/single_checkbox.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/keyboard_shortcuts_dialog.html +19 -0
- wagtail/admin/templates/wagtailadmin/shared/panel.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/set_privacy.html +15 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panels/checks.html +28 -1
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +2 -2
- wagtail/admin/templates/wagtailadmin/{pages/listing/_ordering_header.html → tables/ordering_header.html} +2 -2
- wagtail/admin/templates/wagtailadmin/tables/title_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/widgets/{daterange_input.html → range_input.html} +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/task_chooser/chooser.html +4 -2
- wagtail/admin/templatetags/wagtailadmin_tags.py +41 -22
- wagtail/admin/tests/api/test_pages.py +7 -7
- wagtail/admin/tests/api/test_renderer_classes.py +16 -0
- wagtail/admin/tests/pages/test_create_page.py +34 -2
- wagtail/admin/tests/pages/test_edit_page.py +128 -14
- wagtail/admin/tests/pages/test_explorer_view.py +34 -7
- wagtail/admin/tests/pages/test_reorder_page.py +11 -0
- wagtail/admin/tests/test_collections_views.py +12 -0
- wagtail/admin/tests/test_edit_handlers.py +3 -3
- wagtail/admin/tests/test_filters.py +2 -2
- wagtail/admin/tests/test_keyboard_shortcuts.py +52 -2
- wagtail/admin/tests/test_menu.py +0 -2
- wagtail/admin/tests/test_privacy.py +16 -16
- wagtail/admin/tests/test_templatetags.py +137 -0
- wagtail/admin/tests/test_workflows.py +34 -0
- wagtail/admin/tests/viewsets/test_model_viewset.py +322 -0
- wagtail/admin/ui/tables/orderable.py +73 -0
- wagtail/admin/ui/tables/pages.py +3 -13
- wagtail/admin/views/collection_privacy.py +6 -2
- wagtail/admin/views/generic/__init__.py +1 -0
- wagtail/admin/views/generic/mixins.py +20 -2
- wagtail/admin/views/generic/models.py +67 -1
- wagtail/admin/views/generic/ordering.py +79 -0
- wagtail/admin/views/home.py +3 -3
- wagtail/admin/views/page_privacy.py +5 -2
- wagtail/admin/views/pages/create.py +1 -1
- wagtail/admin/views/pages/edit.py +2 -2
- wagtail/admin/views/pages/listing.py +7 -42
- wagtail/admin/views/pages/move.py +1 -1
- wagtail/admin/views/pages/ordering.py +1 -1
- wagtail/admin/viewsets/base.py +1 -1
- wagtail/admin/viewsets/model.py +49 -1
- wagtail/admin/wagtail_hooks.py +2 -1
- wagtail/admin/widgets/slug.py +10 -10
- wagtail/api/v2/serializers.py +1 -1
- wagtail/api/v2/tests/test_renderer_classes.py +32 -0
- wagtail/apps.py +2 -0
- wagtail/bin/wagtail.py +1 -1
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +14 -14
- wagtail/contrib/forms/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/nl/LC_MESSAGES/django.po +19 -2
- wagtail/contrib/forms/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/ru/LC_MESSAGES/django.po +18 -1
- wagtail/contrib/frontend_cache/tests.py +4 -2
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/redirects/tests/test_tmp_storages.py +20 -0
- wagtail/contrib/redirects/tmp_storages.py +1 -1
- wagtail/contrib/redirects/views.py +3 -3
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/contrib/search_promotions/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/tr/LC_MESSAGES/django.po +43 -3
- wagtail/contrib/search_promotions/static/wagtailsearchpromotions/js/query-chooser-modal.js +1 -1
- wagtail/contrib/search_promotions/views/settings.py +2 -2
- wagtail/contrib/settings/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/cs/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/settings/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/nl/LC_MESSAGES/django.po +6 -2
- wagtail/contrib/settings/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/ru/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/tests/site_specific/test_admin.py +40 -6
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/styleguide/templates/wagtailstyleguide/base.html +5 -5
- wagtail/contrib/table_block/blocks.py +1 -0
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/table_block/static/table_block/js/table.js +1 -1
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/static/typed_table_block/js/typed_table_block.js +1 -1
- wagtail/coreutils.py +5 -5
- wagtail/documents/forms.py +18 -1
- wagtail/documents/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/documents/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/nl/LC_MESSAGES/django.po +9 -0
- wagtail/documents/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/ru/LC_MESSAGES/django.po +9 -0
- wagtail/documents/models.py +1 -1
- wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser-modal.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser-telepath.js +1 -1
- wagtail/documents/static/wagtaildocs/js/document-chooser.js +1 -1
- wagtail/documents/templates/wagtaildocs/documents/add.html +0 -34
- wagtail/documents/tests/test_admin_views.py +132 -26
- wagtail/documents/tests/test_collection_privacy.py +18 -4
- wagtail/documents/tests/test_form_overrides.py +1 -1
- wagtail/documents/tests/test_search.py +21 -8
- wagtail/documents/views/documents.py +1 -1
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/static/wagtailembeds/js/embed-chooser-modal.js +1 -1
- wagtail/images/forms.py +16 -1
- wagtail/images/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/cs/LC_MESSAGES/django.po +12 -1
- wagtail/images/locale/en/LC_MESSAGES/django.po +57 -46
- wagtail/images/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/nl/LC_MESSAGES/django.po +37 -14
- wagtail/images/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/ru/LC_MESSAGES/django.po +20 -1
- wagtail/images/models.py +1 -1
- wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
- wagtail/images/static/wagtailimages/js/focal-point-chooser.js +1 -1
- wagtail/images/static/wagtailimages/js/image-block.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser-modal.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser-telepath.js +1 -1
- wagtail/images/static/wagtailimages/js/image-chooser.js +1 -1
- wagtail/images/static/wagtailimages/js/image-url-generator.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/jquery.Jcrop.min.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/jquery.fileupload-image.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/jquery.fileupload-validate.js +1 -1
- wagtail/images/static/wagtailimages/js/vendor/load-image.min.js +1 -1
- wagtail/images/templates/wagtailimages/chooser/chooser.html +22 -13
- wagtail/images/templates/wagtailimages/chooser/image_preview_column_cell.html +10 -0
- wagtail/images/templates/wagtailimages/chooser/results.html +24 -20
- wagtail/images/templates/wagtailimages/chooser/title_column_cell.html +15 -0
- wagtail/images/templates/wagtailimages/images/add.html +0 -34
- wagtail/images/templates/wagtailimages/images/index.html +3 -3
- wagtail/images/templates/wagtailimages/images/index_results.html +1 -1
- wagtail/images/templates/wagtailimages/images/layout_toggle_button.html +8 -7
- wagtail/images/templatetags/wagtailimages_tags.py +2 -2
- wagtail/images/tests/test_admin_views.py +87 -0
- wagtail/images/tests/test_form_overrides.py +1 -1
- wagtail/images/tests/test_models.py +48 -9
- wagtail/images/views/chooser.py +66 -2
- wagtail/locale/en/LC_MESSAGES/django.po +55 -55
- wagtail/locale/is_IS/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/is_IS/LC_MESSAGES/django.po +3 -3
- wagtail/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/nl/LC_MESSAGES/django.po +11 -2
- wagtail/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/ru/LC_MESSAGES/django.po +11 -1
- wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/nl/LC_MESSAGES/django.po +12 -1
- wagtail/locales/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/ru/LC_MESSAGES/django.po +10 -1
- wagtail/locales/views.py +2 -2
- wagtail/models/orderable.py +10 -0
- wagtail/models/pages.py +9 -11
- wagtail/models/sites.py +1 -1
- wagtail/models/workflows.py +8 -5
- wagtail/project_template/home/tests.py +6 -7
- wagtail/project_template/project_name/settings/base.py +9 -9
- wagtail/project_template/requirements.txt +1 -1
- wagtail/query.py +7 -2
- wagtail/rich_text/rewriters.py +1 -1
- wagtail/search/apps.py +4 -49
- wagtail/search/backends/__init__.py +1 -113
- wagtail/search/backends/base.py +1 -547
- wagtail/search/backends/database/__init__.py +1 -50
- wagtail/search/backends/database/fallback.py +1 -253
- wagtail/search/backends/database/mysql/mysql.py +1 -700
- wagtail/search/backends/database/mysql/query.py +1 -258
- wagtail/search/backends/database/postgres/postgres.py +1 -749
- wagtail/search/backends/database/postgres/query.py +1 -83
- wagtail/search/backends/database/postgres/weights.py +1 -63
- wagtail/search/backends/database/sqlite/query.py +1 -294
- wagtail/search/backends/database/sqlite/sqlite.py +1 -719
- wagtail/search/backends/database/sqlite/utils.py +1 -35
- wagtail/search/backends/deprecation.py +45 -0
- wagtail/search/backends/elasticsearch7.py +18 -1260
- wagtail/search/backends/elasticsearch8.py +21 -96
- wagtail/search/backends/elasticsearch9.py +35 -0
- wagtail/search/backends/opensearch2.py +35 -0
- wagtail/search/backends/opensearch3.py +35 -0
- wagtail/search/index.py +1 -358
- wagtail/search/locale/en/LC_MESSAGES/django.po +2 -10
- wagtail/search/management/commands/update_index.py +1 -205
- wagtail/search/management/commands/wagtail_update_index.py +1 -4
- wagtail/search/models.py +32 -158
- wagtail/search/query.py +1 -114
- wagtail/search/queryset.py +1 -43
- wagtail/search/signal_handlers.py +1 -24
- wagtail/search/tasks.py +1 -10
- wagtail/search/tests/test_elasticsearch.py +22 -0
- wagtail/search/utils.py +1 -206
- wagtail/sites/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +3 -3
- wagtail/snippets/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/ru/LC_MESSAGES/django.po +8 -1
- wagtail/snippets/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/tr/LC_MESSAGES/django.po +8 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
- wagtail/snippets/tests/test_reordering.py +319 -0
- wagtail/snippets/tests/test_snippets.py +65 -12
- wagtail/snippets/views/snippets.py +16 -0
- wagtail/test/numberformat.py +30 -0
- wagtail/test/settings.py +35 -12
- wagtail/test/testapp/fields.py +12 -0
- wagtail/test/testapp/migrations/0056_commentablejsonpage.py +50 -0
- wagtail/test/testapp/migrations/0057_featurecompletetoy_sort_order.py +23 -0
- wagtail/test/testapp/migrations/0058_customlocktask.py +31 -0
- wagtail/test/testapp/models.py +27 -0
- wagtail/test/testapp/views.py +3 -1
- wagtail/test/utils/page_tests.py +17 -17
- wagtail/test/utils/template_tests.py +4 -6
- wagtail/test/utils/wagtail_tests.py +1 -2
- wagtail/tests/test_page_model.py +15 -0
- wagtail/{search/tests → tests}/test_page_search.py +29 -2
- wagtail/tests/test_search_fields.py +69 -0
- wagtail/tests/test_tests.py +62 -6
- wagtail/tests/test_workflow.py +25 -1
- wagtail/users/locale/cs/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/cs/LC_MESSAGES/django.po +3 -0
- wagtail/users/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/users/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/nl/LC_MESSAGES/django.po +6 -3
- wagtail/users/locale/ru/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/ru/LC_MESSAGES/django.po +5 -1
- wagtail/users/locale/tr/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/tr/LC_MESSAGES/django.po +78 -4
- wagtail/users/templates/wagtailusers/users/create.html +2 -0
- wagtail/users/templates/wagtailusers/users/edit.html +2 -0
- wagtail/users/tests/test_admin_views.py +4 -0
- wagtail/users/views/users.py +1 -1
- {wagtail-7.1.2.dist-info → wagtail-7.2rc1.dist-info}/METADATA +7 -6
- {wagtail-7.1.2.dist-info → wagtail-7.2rc1.dist-info}/RECORD +309 -315
- wagtail/admin/templates/wagtailadmin/collection_privacy/set_privacy.html +0 -13
- wagtail/admin/templates/wagtailadmin/page_privacy/set_privacy.html +0 -13
- wagtail/search/tests/__init__.py +0 -0
- wagtail/search/tests/elasticsearch_common_tests.py +0 -251
- wagtail/search/tests/test_backends.py +0 -1215
- wagtail/search/tests/test_db_backend.py +0 -62
- wagtail/search/tests/test_elasticsearch7_backend.py +0 -1452
- wagtail/search/tests/test_elasticsearch8_backend.py +0 -15
- wagtail/search/tests/test_index_functions.py +0 -256
- wagtail/search/tests/test_indexed_class.py +0 -157
- wagtail/search/tests/test_mysql_backend.py +0 -192
- wagtail/search/tests/test_postgres_backend.py +0 -210
- wagtail/search/tests/test_queries.py +0 -332
- wagtail/search/tests/test_related_fields.py +0 -102
- wagtail/search/tests/test_sqlite_backend.py +0 -52
- wagtail/test/search/__init__.py +0 -0
- wagtail/test/search/apps.py +0 -9
- wagtail/test/search/fixtures/search.json +0 -545
- wagtail/test/search/migrations/0001_initial.py +0 -146
- wagtail/test/search/migrations/0002_bookunindexed.py +0 -43
- wagtail/test/search/migrations/0003_book_summary.py +0 -18
- wagtail/test/search/migrations/__init__.py +0 -0
- wagtail/test/search/models.py +0 -137
- /wagtail/admin/templates/wagtailadmin/{pages/listing/_ordering_cell.html → tables/ordering_cell.html} +0 -0
- /wagtail/{search/checks.py → checks.py} +0 -0
- {wagtail-7.1.2.dist-info → wagtail-7.2rc1.dist-info}/WHEEL +0 -0
- {wagtail-7.1.2.dist-info → wagtail-7.2rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-7.1.2.dist-info → wagtail-7.2rc1.dist-info}/licenses/LICENSE +0 -0
- {wagtail-7.1.2.dist-info → wagtail-7.2rc1.dist-info}/top_level.txt +0 -0
|
@@ -1,110 +1,35 @@
|
|
|
1
|
-
from
|
|
2
|
-
from
|
|
1
|
+
from wagtailmodelsearch.backends.elasticsearch8 import * # noqa: F403
|
|
2
|
+
from wagtailmodelsearch.backends.elasticsearch8 import (
|
|
3
|
+
Elasticsearch8AutocompleteQueryCompiler as _Elasticsearch8AutocompleteQueryCompiler,
|
|
4
|
+
)
|
|
5
|
+
from wagtailmodelsearch.backends.elasticsearch8 import (
|
|
6
|
+
Elasticsearch8SearchBackend as _Elasticsearch8SearchBackend,
|
|
7
|
+
)
|
|
8
|
+
from wagtailmodelsearch.backends.elasticsearch8 import (
|
|
9
|
+
Elasticsearch8SearchQueryCompiler as _Elasticsearch8SearchQueryCompiler,
|
|
10
|
+
)
|
|
3
11
|
|
|
4
|
-
from wagtail.search.backends.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Elasticsearch7Mapping,
|
|
8
|
-
Elasticsearch7SearchBackend,
|
|
9
|
-
Elasticsearch7SearchQueryCompiler,
|
|
10
|
-
Elasticsearch7SearchResults,
|
|
12
|
+
from wagtail.search.backends.deprecation import (
|
|
13
|
+
IndexOptionMixin,
|
|
14
|
+
LegacyContentTypeMatchMixin,
|
|
11
15
|
)
|
|
12
|
-
from wagtail.search.index import class_is_indexed
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
class
|
|
18
|
+
class Elasticsearch8SearchQueryCompiler(
|
|
19
|
+
LegacyContentTypeMatchMixin, _Elasticsearch8SearchQueryCompiler
|
|
20
|
+
):
|
|
16
21
|
pass
|
|
17
22
|
|
|
18
23
|
|
|
19
|
-
class
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def delete(self):
|
|
24
|
-
try:
|
|
25
|
-
self.es.indices.delete(index=self.name)
|
|
26
|
-
except NotFoundError:
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
|
-
def refresh(self):
|
|
30
|
-
self.es.indices.refresh(index=self.name)
|
|
31
|
-
|
|
32
|
-
def add_model(self, model):
|
|
33
|
-
# Get mapping
|
|
34
|
-
mapping = self.mapping_class(model)
|
|
35
|
-
|
|
36
|
-
# Put mapping
|
|
37
|
-
self.es.indices.put_mapping(index=self.name, **mapping.get_mapping())
|
|
38
|
-
|
|
39
|
-
def add_item(self, item):
|
|
40
|
-
# Make sure the object can be indexed
|
|
41
|
-
if not class_is_indexed(item.__class__):
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
# Get mapping
|
|
45
|
-
mapping = self.mapping_class(item.__class__)
|
|
46
|
-
|
|
47
|
-
# Add document to index
|
|
48
|
-
self.es.index(
|
|
49
|
-
index=self.name,
|
|
50
|
-
document=mapping.get_document(item),
|
|
51
|
-
id=mapping.get_document_id(item),
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class Elasticsearch8SearchQueryCompiler(Elasticsearch7SearchQueryCompiler):
|
|
56
|
-
mapping_class = Elasticsearch8Mapping
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class Elasticsearch8SearchResults(Elasticsearch7SearchResults):
|
|
60
|
-
def _backend_do_search(self, body, **kwargs):
|
|
61
|
-
# As of Elasticsearch 7.15, the 'body' parameter is deprecated; instead, the top-level
|
|
62
|
-
# keys of the body dict are now kwargs in their own right
|
|
63
|
-
return self.backend.es.search(**body, **kwargs)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class Elasticsearch8AutocompleteQueryCompiler(Elasticsearch7AutocompleteQueryCompiler):
|
|
67
|
-
mapping_class = Elasticsearch8Mapping
|
|
24
|
+
class Elasticsearch8AutocompleteQueryCompiler(
|
|
25
|
+
LegacyContentTypeMatchMixin, _Elasticsearch8AutocompleteQueryCompiler
|
|
26
|
+
):
|
|
27
|
+
pass
|
|
68
28
|
|
|
69
29
|
|
|
70
|
-
class Elasticsearch8SearchBackend(
|
|
71
|
-
mapping_class = Elasticsearch8Mapping
|
|
72
|
-
index_class = Elasticsearch8Index
|
|
30
|
+
class Elasticsearch8SearchBackend(IndexOptionMixin, _Elasticsearch8SearchBackend):
|
|
73
31
|
query_compiler_class = Elasticsearch8SearchQueryCompiler
|
|
74
32
|
autocomplete_query_compiler_class = Elasticsearch8AutocompleteQueryCompiler
|
|
75
|
-
results_class = Elasticsearch8SearchResults
|
|
76
|
-
timeout_kwarg_name = "request_timeout"
|
|
77
|
-
|
|
78
|
-
def _get_host_config_from_url(self, url):
|
|
79
|
-
"""Given a parsed URL, return the host configuration to be added to self.hosts"""
|
|
80
|
-
use_ssl = url.scheme == "https"
|
|
81
|
-
port = url.port or (443 if use_ssl else 80)
|
|
82
|
-
|
|
83
|
-
# the verify_certs and http_auth options are no longer valid in Elasticsearch 8
|
|
84
|
-
return {
|
|
85
|
-
"host": url.hostname,
|
|
86
|
-
"port": port,
|
|
87
|
-
"path_prefix": url.path,
|
|
88
|
-
"scheme": url.scheme,
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
def _get_options_from_host_urls(self, urls):
|
|
92
|
-
"""Given a list of parsed URLs, return a dict of additional options to be passed into the
|
|
93
|
-
Elasticsearch constructor; necessary for options that aren't valid as part of the 'hosts' config"""
|
|
94
|
-
opts = super()._get_options_from_host_urls(urls)
|
|
95
|
-
|
|
96
|
-
basic_auth = (urls[0].username, urls[0].password)
|
|
97
|
-
# Ensure that all urls have the same credentials
|
|
98
|
-
if any((url.username, url.password) != basic_auth for url in urls):
|
|
99
|
-
raise ImproperlyConfigured(
|
|
100
|
-
"Elasticsearch host configuration is invalid. "
|
|
101
|
-
"Elasticsearch 8 does not support multiple hosts with differing authentication credentials."
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
if basic_auth != (None, None):
|
|
105
|
-
opts["basic_auth"] = basic_auth
|
|
106
|
-
|
|
107
|
-
return opts
|
|
108
33
|
|
|
109
34
|
|
|
110
35
|
SearchBackend = Elasticsearch8SearchBackend
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from wagtailmodelsearch.backends.elasticsearch9 import * # noqa: F403
|
|
2
|
+
from wagtailmodelsearch.backends.elasticsearch9 import (
|
|
3
|
+
Elasticsearch9AutocompleteQueryCompiler as _Elasticsearch9AutocompleteQueryCompiler,
|
|
4
|
+
)
|
|
5
|
+
from wagtailmodelsearch.backends.elasticsearch9 import (
|
|
6
|
+
Elasticsearch9SearchBackend as _Elasticsearch9SearchBackend,
|
|
7
|
+
)
|
|
8
|
+
from wagtailmodelsearch.backends.elasticsearch9 import (
|
|
9
|
+
Elasticsearch9SearchQueryCompiler as _Elasticsearch9SearchQueryCompiler,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from wagtail.search.backends.deprecation import (
|
|
13
|
+
IndexOptionMixin,
|
|
14
|
+
LegacyContentTypeMatchMixin,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Elasticsearch9SearchQueryCompiler(
|
|
19
|
+
LegacyContentTypeMatchMixin, _Elasticsearch9SearchQueryCompiler
|
|
20
|
+
):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Elasticsearch9AutocompleteQueryCompiler(
|
|
25
|
+
LegacyContentTypeMatchMixin, _Elasticsearch9AutocompleteQueryCompiler
|
|
26
|
+
):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Elasticsearch9SearchBackend(IndexOptionMixin, _Elasticsearch9SearchBackend):
|
|
31
|
+
query_compiler_class = Elasticsearch9SearchQueryCompiler
|
|
32
|
+
autocomplete_query_compiler_class = Elasticsearch9AutocompleteQueryCompiler
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
SearchBackend = Elasticsearch9SearchBackend
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from wagtailmodelsearch.backends.opensearch2 import * # noqa: F403
|
|
2
|
+
from wagtailmodelsearch.backends.opensearch2 import (
|
|
3
|
+
OpenSearch2AutocompleteQueryCompiler as _OpenSearch2AutocompleteQueryCompiler,
|
|
4
|
+
)
|
|
5
|
+
from wagtailmodelsearch.backends.opensearch2 import (
|
|
6
|
+
OpenSearch2SearchBackend as _OpenSearch2SearchBackend,
|
|
7
|
+
)
|
|
8
|
+
from wagtailmodelsearch.backends.opensearch2 import (
|
|
9
|
+
OpenSearch2SearchQueryCompiler as _OpenSearch2SearchQueryCompiler,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from wagtail.search.backends.deprecation import (
|
|
13
|
+
IndexOptionMixin,
|
|
14
|
+
LegacyContentTypeMatchMixin,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OpenSearch2SearchQueryCompiler(
|
|
19
|
+
LegacyContentTypeMatchMixin, _OpenSearch2SearchQueryCompiler
|
|
20
|
+
):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class OpenSearch2AutocompleteQueryCompiler(
|
|
25
|
+
LegacyContentTypeMatchMixin, _OpenSearch2AutocompleteQueryCompiler
|
|
26
|
+
):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class OpenSearch2SearchBackend(IndexOptionMixin, _OpenSearch2SearchBackend):
|
|
31
|
+
query_compiler_class = OpenSearch2SearchQueryCompiler
|
|
32
|
+
autocomplete_query_compiler_class = OpenSearch2AutocompleteQueryCompiler
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
SearchBackend = OpenSearch2SearchBackend
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from wagtailmodelsearch.backends.opensearch3 import * # noqa: F403
|
|
2
|
+
from wagtailmodelsearch.backends.opensearch3 import (
|
|
3
|
+
OpenSearch3AutocompleteQueryCompiler as _OpenSearch3AutocompleteQueryCompiler,
|
|
4
|
+
)
|
|
5
|
+
from wagtailmodelsearch.backends.opensearch3 import (
|
|
6
|
+
OpenSearch3SearchBackend as _OpenSearch3SearchBackend,
|
|
7
|
+
)
|
|
8
|
+
from wagtailmodelsearch.backends.opensearch3 import (
|
|
9
|
+
OpenSearch3SearchQueryCompiler as _OpenSearch3SearchQueryCompiler,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from wagtail.search.backends.deprecation import (
|
|
13
|
+
IndexOptionMixin,
|
|
14
|
+
LegacyContentTypeMatchMixin,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OpenSearch3SearchQueryCompiler(
|
|
19
|
+
LegacyContentTypeMatchMixin, _OpenSearch3SearchQueryCompiler
|
|
20
|
+
):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class OpenSearch3AutocompleteQueryCompiler(
|
|
25
|
+
LegacyContentTypeMatchMixin, _OpenSearch3AutocompleteQueryCompiler
|
|
26
|
+
):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class OpenSearch3SearchBackend(IndexOptionMixin, _OpenSearch3SearchBackend):
|
|
31
|
+
query_compiler_class = OpenSearch3SearchQueryCompiler
|
|
32
|
+
autocomplete_query_compiler_class = OpenSearch3AutocompleteQueryCompiler
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
SearchBackend = OpenSearch3SearchBackend
|
wagtail/search/index.py
CHANGED
|
@@ -1,358 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import logging
|
|
3
|
-
|
|
4
|
-
from django.apps import apps
|
|
5
|
-
from django.core import checks
|
|
6
|
-
from django.core.exceptions import FieldDoesNotExist
|
|
7
|
-
from django.db import models
|
|
8
|
-
from django.db.models.fields.related import ForeignObjectRel, OneToOneRel, RelatedField
|
|
9
|
-
from modelcluster.fields import ParentalManyToManyField
|
|
10
|
-
|
|
11
|
-
from wagtail.search.backends import get_search_backends_with_name
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger("wagtail.search.index")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class Indexed:
|
|
17
|
-
@classmethod
|
|
18
|
-
def indexed_get_parent(cls, require_model=True):
|
|
19
|
-
for base in cls.__bases__:
|
|
20
|
-
if issubclass(base, Indexed) and (
|
|
21
|
-
issubclass(base, models.Model) or require_model is False
|
|
22
|
-
):
|
|
23
|
-
return base
|
|
24
|
-
|
|
25
|
-
@classmethod
|
|
26
|
-
def indexed_get_content_type(cls):
|
|
27
|
-
# Work out content type
|
|
28
|
-
content_type = (cls._meta.app_label + "_" + cls.__name__).lower()
|
|
29
|
-
|
|
30
|
-
# Get parent content type
|
|
31
|
-
parent = cls.indexed_get_parent()
|
|
32
|
-
if parent:
|
|
33
|
-
parent_content_type = parent.indexed_get_content_type()
|
|
34
|
-
return parent_content_type + "_" + content_type
|
|
35
|
-
else:
|
|
36
|
-
return content_type
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
def indexed_get_toplevel_content_type(cls):
|
|
40
|
-
# Get parent content type
|
|
41
|
-
parent = cls.indexed_get_parent()
|
|
42
|
-
if parent:
|
|
43
|
-
return parent.indexed_get_content_type()
|
|
44
|
-
else:
|
|
45
|
-
# At toplevel, return this content type
|
|
46
|
-
return (cls._meta.app_label + "_" + cls.__name__).lower()
|
|
47
|
-
|
|
48
|
-
@classmethod
|
|
49
|
-
def get_search_fields(cls):
|
|
50
|
-
search_fields = {}
|
|
51
|
-
|
|
52
|
-
for field in cls.search_fields:
|
|
53
|
-
search_fields[(type(field), field.field_name)] = field
|
|
54
|
-
|
|
55
|
-
return list(search_fields.values())
|
|
56
|
-
|
|
57
|
-
@classmethod
|
|
58
|
-
def get_searchable_search_fields(cls):
|
|
59
|
-
return [
|
|
60
|
-
field for field in cls.get_search_fields() if isinstance(field, SearchField)
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
@classmethod
|
|
64
|
-
def get_autocomplete_search_fields(cls):
|
|
65
|
-
return [
|
|
66
|
-
field
|
|
67
|
-
for field in cls.get_search_fields()
|
|
68
|
-
if isinstance(field, AutocompleteField)
|
|
69
|
-
]
|
|
70
|
-
|
|
71
|
-
@classmethod
|
|
72
|
-
def get_filterable_search_fields(cls):
|
|
73
|
-
return [
|
|
74
|
-
field for field in cls.get_search_fields() if isinstance(field, FilterField)
|
|
75
|
-
]
|
|
76
|
-
|
|
77
|
-
@classmethod
|
|
78
|
-
def get_indexed_objects(cls):
|
|
79
|
-
queryset = cls.objects.all()
|
|
80
|
-
|
|
81
|
-
# Add prefetch/select related for RelatedFields
|
|
82
|
-
for field in cls.get_search_fields():
|
|
83
|
-
if isinstance(field, RelatedFields):
|
|
84
|
-
queryset = field.select_on_queryset(queryset)
|
|
85
|
-
|
|
86
|
-
return queryset
|
|
87
|
-
|
|
88
|
-
def get_indexed_instance(self):
|
|
89
|
-
"""
|
|
90
|
-
If the indexed model uses multi table inheritance, override this method
|
|
91
|
-
to return the instance in its most specific class so it reindexes properly.
|
|
92
|
-
"""
|
|
93
|
-
return self
|
|
94
|
-
|
|
95
|
-
@classmethod
|
|
96
|
-
def _has_field(cls, name):
|
|
97
|
-
try:
|
|
98
|
-
cls._meta.get_field(name)
|
|
99
|
-
return True
|
|
100
|
-
except FieldDoesNotExist:
|
|
101
|
-
return hasattr(cls, name)
|
|
102
|
-
|
|
103
|
-
@classmethod
|
|
104
|
-
def check(cls, **kwargs):
|
|
105
|
-
errors = super().check(**kwargs)
|
|
106
|
-
errors.extend(cls._check_search_fields(**kwargs))
|
|
107
|
-
return errors
|
|
108
|
-
|
|
109
|
-
@classmethod
|
|
110
|
-
def _check_search_fields(cls, **kwargs):
|
|
111
|
-
errors = []
|
|
112
|
-
for field in cls.get_search_fields():
|
|
113
|
-
message = "{model}.search_fields contains non-existent field '{name}'"
|
|
114
|
-
if not cls._has_field(field.field_name):
|
|
115
|
-
errors.append(
|
|
116
|
-
checks.Warning(
|
|
117
|
-
message.format(model=cls.__name__, name=field.field_name),
|
|
118
|
-
obj=cls,
|
|
119
|
-
id="wagtailsearch.W004",
|
|
120
|
-
)
|
|
121
|
-
)
|
|
122
|
-
return errors
|
|
123
|
-
|
|
124
|
-
search_fields = []
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def get_indexed_models():
|
|
128
|
-
return [
|
|
129
|
-
model
|
|
130
|
-
for model in apps.get_models()
|
|
131
|
-
if issubclass(model, Indexed)
|
|
132
|
-
and not model._meta.abstract
|
|
133
|
-
and model.search_fields
|
|
134
|
-
]
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def class_is_indexed(cls):
|
|
138
|
-
return (
|
|
139
|
-
issubclass(cls, Indexed)
|
|
140
|
-
and issubclass(cls, models.Model)
|
|
141
|
-
and not cls._meta.abstract
|
|
142
|
-
and cls.search_fields
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def get_indexed_instance(instance, check_exists=True):
|
|
147
|
-
indexed_instance = instance.get_indexed_instance()
|
|
148
|
-
if indexed_instance is None:
|
|
149
|
-
return
|
|
150
|
-
|
|
151
|
-
# Make sure that the instance is in its class's indexed objects
|
|
152
|
-
if (
|
|
153
|
-
check_exists
|
|
154
|
-
and not type(indexed_instance)
|
|
155
|
-
.get_indexed_objects()
|
|
156
|
-
.filter(pk=indexed_instance.pk)
|
|
157
|
-
.exists()
|
|
158
|
-
):
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
return indexed_instance
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def insert_or_update_object(instance):
|
|
165
|
-
indexed_instance = get_indexed_instance(instance)
|
|
166
|
-
|
|
167
|
-
if indexed_instance:
|
|
168
|
-
for backend_name, backend in get_search_backends_with_name(
|
|
169
|
-
with_auto_update=True
|
|
170
|
-
):
|
|
171
|
-
try:
|
|
172
|
-
backend.add(indexed_instance)
|
|
173
|
-
except Exception:
|
|
174
|
-
# Log all errors
|
|
175
|
-
logger.exception(
|
|
176
|
-
"Exception raised while adding %r into the '%s' search backend",
|
|
177
|
-
indexed_instance,
|
|
178
|
-
backend_name,
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
# Catch exceptions for backends that use an external service like Elasticsearch
|
|
182
|
-
# This is to prevent data loss if that external service was to go down and the user's
|
|
183
|
-
# save request was to fail.
|
|
184
|
-
# But note that we don't want this for database backends though as an error during a
|
|
185
|
-
# database transaction will require the transaction to be rolled back anyway. So If
|
|
186
|
-
# we caught the error here, the request will only crash again when the next database
|
|
187
|
-
# query is made but then the error message wouldn't be very informative.
|
|
188
|
-
if not backend.catch_indexing_errors:
|
|
189
|
-
raise
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def remove_object(instance):
|
|
193
|
-
indexed_instance = get_indexed_instance(instance, check_exists=False)
|
|
194
|
-
|
|
195
|
-
if indexed_instance:
|
|
196
|
-
for backend_name, backend in get_search_backends_with_name(
|
|
197
|
-
with_auto_update=True
|
|
198
|
-
):
|
|
199
|
-
try:
|
|
200
|
-
backend.delete(indexed_instance)
|
|
201
|
-
except Exception:
|
|
202
|
-
# Log all errors
|
|
203
|
-
logger.exception(
|
|
204
|
-
"Exception raised while deleting %r from the '%s' search backend",
|
|
205
|
-
indexed_instance,
|
|
206
|
-
backend_name,
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
# Only catch the exception if the backend requires this
|
|
210
|
-
# See the comments in insert_or_update_object for an explanation
|
|
211
|
-
if not backend.catch_indexing_errors:
|
|
212
|
-
raise
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
class BaseField:
|
|
216
|
-
def __init__(self, field_name, **kwargs):
|
|
217
|
-
self.field_name = field_name
|
|
218
|
-
self.kwargs = kwargs
|
|
219
|
-
|
|
220
|
-
def get_field(self, cls):
|
|
221
|
-
return cls._meta.get_field(self.field_name)
|
|
222
|
-
|
|
223
|
-
def get_attname(self, cls):
|
|
224
|
-
try:
|
|
225
|
-
field = self.get_field(cls)
|
|
226
|
-
return field.attname
|
|
227
|
-
except FieldDoesNotExist:
|
|
228
|
-
return self.field_name
|
|
229
|
-
|
|
230
|
-
def get_definition_model(self, cls):
|
|
231
|
-
try:
|
|
232
|
-
field = self.get_field(cls)
|
|
233
|
-
return field.model
|
|
234
|
-
except FieldDoesNotExist:
|
|
235
|
-
# Find where it was defined by walking the inheritance tree
|
|
236
|
-
for base_cls in inspect.getmro(cls):
|
|
237
|
-
if self.field_name in base_cls.__dict__:
|
|
238
|
-
return base_cls
|
|
239
|
-
|
|
240
|
-
def get_type(self, cls):
|
|
241
|
-
if "type" in self.kwargs:
|
|
242
|
-
return self.kwargs["type"]
|
|
243
|
-
|
|
244
|
-
try:
|
|
245
|
-
field = self.get_field(cls)
|
|
246
|
-
|
|
247
|
-
# Follow foreign keys to find underlying type
|
|
248
|
-
# We use a while loop as it's possible for a foreign key
|
|
249
|
-
# to target a foreign key in another model.
|
|
250
|
-
# (for example, a foreign key to a child page model will
|
|
251
|
-
# point to the `page_ptr_id` field so we need to follow this
|
|
252
|
-
# second foreign key to find the `id`` field in the Page model)
|
|
253
|
-
while isinstance(field, RelatedField):
|
|
254
|
-
field = field.target_field
|
|
255
|
-
|
|
256
|
-
return field.get_internal_type()
|
|
257
|
-
|
|
258
|
-
except FieldDoesNotExist:
|
|
259
|
-
return "CharField"
|
|
260
|
-
|
|
261
|
-
def get_value(self, obj):
|
|
262
|
-
from taggit.managers import TaggableManager
|
|
263
|
-
|
|
264
|
-
try:
|
|
265
|
-
field = self.get_field(obj.__class__)
|
|
266
|
-
value = field.value_from_object(obj)
|
|
267
|
-
if hasattr(field, "get_searchable_content"):
|
|
268
|
-
value = field.get_searchable_content(value)
|
|
269
|
-
elif isinstance(field, TaggableManager):
|
|
270
|
-
# As of django-taggit 1.0, value_from_object returns a list of Tag objects,
|
|
271
|
-
# which matches what we want
|
|
272
|
-
pass
|
|
273
|
-
elif isinstance(field, RelatedField):
|
|
274
|
-
# The type of the ForeignKey may have a get_searchable_content method that we should
|
|
275
|
-
# call. Firstly we need to find the field its referencing but it may be referencing
|
|
276
|
-
# another RelatedField (eg an FK to page_ptr_id) so we need to run this in a while
|
|
277
|
-
# loop to find the actual remote field.
|
|
278
|
-
remote_field = field
|
|
279
|
-
while isinstance(remote_field, RelatedField):
|
|
280
|
-
remote_field = remote_field.target_field
|
|
281
|
-
|
|
282
|
-
if hasattr(remote_field, "get_searchable_content"):
|
|
283
|
-
value = remote_field.get_searchable_content(value)
|
|
284
|
-
return value
|
|
285
|
-
except FieldDoesNotExist:
|
|
286
|
-
value = getattr(obj, self.field_name, None)
|
|
287
|
-
if hasattr(value, "__call__"):
|
|
288
|
-
value = value()
|
|
289
|
-
return value
|
|
290
|
-
|
|
291
|
-
def __repr__(self):
|
|
292
|
-
return f"<{self.__class__.__name__}: {self.field_name}>"
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
class SearchField(BaseField):
|
|
296
|
-
def __init__(self, field_name, boost=None, **kwargs):
|
|
297
|
-
super().__init__(field_name, **kwargs)
|
|
298
|
-
self.boost = boost
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
class AutocompleteField(BaseField):
|
|
302
|
-
pass
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
class FilterField(BaseField):
|
|
306
|
-
pass
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
class RelatedFields:
|
|
310
|
-
def __init__(self, field_name, fields):
|
|
311
|
-
self.field_name = field_name
|
|
312
|
-
self.fields = fields
|
|
313
|
-
|
|
314
|
-
def get_field(self, cls):
|
|
315
|
-
return cls._meta.get_field(self.field_name)
|
|
316
|
-
|
|
317
|
-
def get_definition_model(self, cls):
|
|
318
|
-
field = self.get_field(cls)
|
|
319
|
-
return field.model
|
|
320
|
-
|
|
321
|
-
def get_value(self, obj):
|
|
322
|
-
field = self.get_field(obj.__class__)
|
|
323
|
-
|
|
324
|
-
if isinstance(field, (RelatedField, ForeignObjectRel)):
|
|
325
|
-
return getattr(obj, self.field_name)
|
|
326
|
-
|
|
327
|
-
def select_on_queryset(self, queryset):
|
|
328
|
-
"""
|
|
329
|
-
This method runs either prefetch_related or select_related on the queryset
|
|
330
|
-
to improve indexing speed of the relation.
|
|
331
|
-
|
|
332
|
-
It decides which method to call based on the number of related objects:
|
|
333
|
-
- single (eg ForeignKey, OneToOne), it runs select_related
|
|
334
|
-
- multiple (eg ManyToMany, reverse ForeignKey) it runs prefetch_related
|
|
335
|
-
"""
|
|
336
|
-
try:
|
|
337
|
-
field = self.get_field(queryset.model)
|
|
338
|
-
except FieldDoesNotExist:
|
|
339
|
-
return queryset
|
|
340
|
-
|
|
341
|
-
if isinstance(field, RelatedField) and not isinstance(
|
|
342
|
-
field, ParentalManyToManyField
|
|
343
|
-
):
|
|
344
|
-
if field.many_to_one or field.one_to_one:
|
|
345
|
-
queryset = queryset.select_related(self.field_name)
|
|
346
|
-
elif field.one_to_many or field.many_to_many:
|
|
347
|
-
queryset = queryset.prefetch_related(self.field_name)
|
|
348
|
-
|
|
349
|
-
elif isinstance(field, ForeignObjectRel):
|
|
350
|
-
# Reverse relation
|
|
351
|
-
if isinstance(field, OneToOneRel):
|
|
352
|
-
# select_related for reverse OneToOneField
|
|
353
|
-
queryset = queryset.select_related(self.field_name)
|
|
354
|
-
else:
|
|
355
|
-
# prefetch_related for anything else (reverse ForeignKey/ManyToManyField)
|
|
356
|
-
queryset = queryset.prefetch_related(self.field_name)
|
|
357
|
-
|
|
358
|
-
return queryset
|
|
1
|
+
from wagtailmodelsearch.index import * # noqa: F403
|
|
@@ -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: 2025-
|
|
11
|
+
"POT-Creation-Date: 2025-10-23 16:45+0100\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"
|
|
@@ -18,14 +18,6 @@ msgstr ""
|
|
|
18
18
|
"Content-Transfer-Encoding: 8bit\n"
|
|
19
19
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
20
20
|
|
|
21
|
-
#: apps.py:
|
|
21
|
+
#: apps.py:8
|
|
22
22
|
msgid "Wagtail search"
|
|
23
23
|
msgstr ""
|
|
24
|
-
|
|
25
|
-
#: models.py:65
|
|
26
|
-
msgid "index entry"
|
|
27
|
-
msgstr ""
|
|
28
|
-
|
|
29
|
-
#: models.py:66
|
|
30
|
-
msgid "index entries"
|
|
31
|
-
msgstr ""
|