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,205 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
from django.conf import settings
|
|
4
|
-
from django.core.management.base import BaseCommand
|
|
5
|
-
from django.db import transaction
|
|
6
|
-
|
|
7
|
-
from wagtail.search.backends import get_search_backend
|
|
8
|
-
from wagtail.search.index import get_indexed_models
|
|
9
|
-
|
|
10
|
-
DEFAULT_CHUNK_SIZE = 1000
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def group_models_by_index(backend, models):
|
|
14
|
-
"""
|
|
15
|
-
This takes a search backend and a list of models. By calling the
|
|
16
|
-
get_index_for_model method on the search backend, it groups the models into
|
|
17
|
-
the indices that they will be indexed into.
|
|
18
|
-
|
|
19
|
-
It returns an ordered mapping of indices to lists of models within each
|
|
20
|
-
index.
|
|
21
|
-
|
|
22
|
-
For example, Elasticsearch 2 requires all page models to be together, but
|
|
23
|
-
separate from other content types (eg, images and documents) to prevent
|
|
24
|
-
field mapping collisions:
|
|
25
|
-
|
|
26
|
-
>>> group_models_by_index(elasticsearch2_backend, [
|
|
27
|
-
... wagtailcore.Page,
|
|
28
|
-
... myapp.HomePage,
|
|
29
|
-
... myapp.StandardPage,
|
|
30
|
-
... wagtailimages.Image
|
|
31
|
-
... ])
|
|
32
|
-
{
|
|
33
|
-
<Index wagtailcore_page>: [wagtailcore.Page, myapp.HomePage, myapp.StandardPage],
|
|
34
|
-
<Index wagtailimages_image>: [wagtailimages.Image],
|
|
35
|
-
}
|
|
36
|
-
"""
|
|
37
|
-
indices = {}
|
|
38
|
-
models_by_index = collections.OrderedDict()
|
|
39
|
-
|
|
40
|
-
for model in models:
|
|
41
|
-
index = backend.get_index_for_model(model)
|
|
42
|
-
|
|
43
|
-
if index:
|
|
44
|
-
indices.setdefault(index.name, index)
|
|
45
|
-
models_by_index.setdefault(index.name, [])
|
|
46
|
-
models_by_index[index.name].append(model)
|
|
47
|
-
|
|
48
|
-
return collections.OrderedDict(
|
|
49
|
-
[
|
|
50
|
-
(indices[index_name], index_models)
|
|
51
|
-
for index_name, index_models in models_by_index.items()
|
|
52
|
-
]
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
class Command(BaseCommand):
|
|
57
|
-
def write(self, *args, **kwargs):
|
|
58
|
-
"""Helper function that respects verbosity when printing."""
|
|
59
|
-
if self.verbosity > 0:
|
|
60
|
-
self.stdout.write(*args, **kwargs)
|
|
61
|
-
|
|
62
|
-
def update_backend(
|
|
63
|
-
self, backend_name, schema_only=False, chunk_size=DEFAULT_CHUNK_SIZE
|
|
64
|
-
):
|
|
65
|
-
self.write("Updating backend: " + backend_name)
|
|
66
|
-
|
|
67
|
-
backend = get_search_backend(backend_name)
|
|
68
|
-
|
|
69
|
-
if not backend.rebuilder_class:
|
|
70
|
-
self.write("Backend '%s' doesn't require rebuilding" % backend_name)
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
models_grouped_by_index = group_models_by_index(
|
|
74
|
-
backend, get_indexed_models()
|
|
75
|
-
).items()
|
|
76
|
-
if not models_grouped_by_index:
|
|
77
|
-
self.write(backend_name + ": No indices to rebuild")
|
|
78
|
-
|
|
79
|
-
for index, models in models_grouped_by_index:
|
|
80
|
-
self.write(backend_name + ": Rebuilding index %s" % index.name)
|
|
81
|
-
|
|
82
|
-
# Start rebuild
|
|
83
|
-
rebuilder = backend.rebuilder_class(index)
|
|
84
|
-
index = rebuilder.start()
|
|
85
|
-
|
|
86
|
-
# Add models
|
|
87
|
-
for model in models:
|
|
88
|
-
index.add_model(model)
|
|
89
|
-
|
|
90
|
-
# Add objects
|
|
91
|
-
object_count = 0
|
|
92
|
-
if not schema_only:
|
|
93
|
-
for model in models:
|
|
94
|
-
self.write(
|
|
95
|
-
"{}: {}.{} ".format(
|
|
96
|
-
backend_name, model._meta.app_label, model.__name__
|
|
97
|
-
).ljust(35),
|
|
98
|
-
ending="",
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# Add items (chunk_size at a time)
|
|
102
|
-
for chunk in self.print_iter_progress(
|
|
103
|
-
self.queryset_chunks(
|
|
104
|
-
model.get_indexed_objects().order_by("pk"), chunk_size
|
|
105
|
-
)
|
|
106
|
-
):
|
|
107
|
-
index.add_items(model, chunk)
|
|
108
|
-
object_count += len(chunk)
|
|
109
|
-
|
|
110
|
-
self.print_newline()
|
|
111
|
-
|
|
112
|
-
# Finish rebuild
|
|
113
|
-
rebuilder.finish()
|
|
114
|
-
|
|
115
|
-
self.write(backend_name + ": indexed %d objects" % object_count)
|
|
116
|
-
self.print_newline()
|
|
117
|
-
|
|
118
|
-
def add_arguments(self, parser):
|
|
119
|
-
parser.add_argument(
|
|
120
|
-
"--backend",
|
|
121
|
-
action="store",
|
|
122
|
-
dest="backend_name",
|
|
123
|
-
default=None,
|
|
124
|
-
help="Specify a backend to update",
|
|
125
|
-
)
|
|
126
|
-
parser.add_argument(
|
|
127
|
-
"--schema-only",
|
|
128
|
-
action="store_true",
|
|
129
|
-
dest="schema_only",
|
|
130
|
-
default=False,
|
|
131
|
-
help="Prevents loading any data into the index",
|
|
132
|
-
)
|
|
133
|
-
parser.add_argument(
|
|
134
|
-
"--chunk_size",
|
|
135
|
-
action="store",
|
|
136
|
-
dest="chunk_size",
|
|
137
|
-
default=DEFAULT_CHUNK_SIZE,
|
|
138
|
-
type=int,
|
|
139
|
-
help="Set number of records to be fetched at once for inserting into the index",
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
def handle(self, **options):
|
|
143
|
-
self.verbosity = options["verbosity"]
|
|
144
|
-
|
|
145
|
-
# Get list of backends to index
|
|
146
|
-
if options["backend_name"]:
|
|
147
|
-
# index only the passed backend
|
|
148
|
-
backend_names = [options["backend_name"]]
|
|
149
|
-
elif hasattr(settings, "WAGTAILSEARCH_BACKENDS"):
|
|
150
|
-
# index all backends listed in settings
|
|
151
|
-
backend_names = settings.WAGTAILSEARCH_BACKENDS.keys()
|
|
152
|
-
else:
|
|
153
|
-
# index the 'default' backend only
|
|
154
|
-
backend_names = ["default"]
|
|
155
|
-
|
|
156
|
-
# Update backends
|
|
157
|
-
for backend_name in backend_names:
|
|
158
|
-
self.update_backend(
|
|
159
|
-
backend_name,
|
|
160
|
-
schema_only=options.get("schema_only", False),
|
|
161
|
-
chunk_size=options.get("chunk_size"),
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
def print_newline(self):
|
|
165
|
-
self.write("")
|
|
166
|
-
|
|
167
|
-
def print_iter_progress(self, iterable):
|
|
168
|
-
"""
|
|
169
|
-
Print a progress meter while iterating over an iterable. Use it as part
|
|
170
|
-
of a ``for`` loop::
|
|
171
|
-
|
|
172
|
-
for item in self.print_iter_progress(big_long_list):
|
|
173
|
-
self.do_expensive_computation(item)
|
|
174
|
-
|
|
175
|
-
A ``.`` character is printed for every value in the iterable,
|
|
176
|
-
a space every 10 items, and a new line every 50 items.
|
|
177
|
-
"""
|
|
178
|
-
for i, value in enumerate(iterable, start=1):
|
|
179
|
-
yield value
|
|
180
|
-
self.write(".", ending="")
|
|
181
|
-
if i % 40 == 0:
|
|
182
|
-
self.print_newline()
|
|
183
|
-
self.write(" " * 35, ending="")
|
|
184
|
-
|
|
185
|
-
elif i % 10 == 0:
|
|
186
|
-
self.write(" ", ending="")
|
|
187
|
-
|
|
188
|
-
self.stdout.flush()
|
|
189
|
-
|
|
190
|
-
# Atomic so the count of models doesn't change as it is iterated
|
|
191
|
-
@transaction.atomic
|
|
192
|
-
def queryset_chunks(self, qs, chunk_size=DEFAULT_CHUNK_SIZE):
|
|
193
|
-
"""
|
|
194
|
-
Yield a queryset in chunks of at most ``chunk_size``. The chunk yielded
|
|
195
|
-
will be a list, not a queryset. Iterating over the chunks is done in a
|
|
196
|
-
transaction so that the order and count of items in the queryset
|
|
197
|
-
remains stable.
|
|
198
|
-
"""
|
|
199
|
-
i = 0
|
|
200
|
-
while True:
|
|
201
|
-
items = list(qs[i * chunk_size :][:chunk_size])
|
|
202
|
-
if not items:
|
|
203
|
-
break
|
|
204
|
-
yield items
|
|
205
|
-
i += 1
|
|
1
|
+
from wagtailmodelsearch.management.commands.rebuild_modelsearch_index import * # noqa: F403
|
|
@@ -1,4 +1 @@
|
|
|
1
|
-
|
|
2
|
-
# that implement an update_index command (such as django-haystack)
|
|
3
|
-
|
|
4
|
-
from wagtail.search.management.commands.update_index import Command # NOQA: F401
|
|
1
|
+
from wagtailmodelsearch.management.commands.rebuild_modelsearch_index import * # noqa: F403
|
wagtail/search/models.py
CHANGED
|
@@ -1,175 +1,49 @@
|
|
|
1
|
-
from django.
|
|
2
|
-
from django.
|
|
3
|
-
from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from django.db.models.functions import Cast
|
|
8
|
-
from django.db.models.sql.where import WhereNode
|
|
9
|
-
from django.utils.translation import gettext_lazy as _
|
|
1
|
+
from django.db import models
|
|
2
|
+
from django.db.models import OneToOneField
|
|
3
|
+
from wagtailmodelsearch.abstract_models import (
|
|
4
|
+
AbstractIndexEntry,
|
|
5
|
+
AbstractSQLiteFTSIndexEntry,
|
|
6
|
+
)
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
# We import abstract models from the modelsearch app and define concrete implementations here in the
|
|
9
|
+
# wagtail.search app. This preserves backwards compatibility for existing Wagtail projects that have
|
|
10
|
+
# these models in the wagtailsearch namespace, and avoids the need to add modelsearch to INSTALLED_APPS.
|
|
13
11
|
|
|
14
12
|
|
|
15
|
-
class
|
|
16
|
-
auto_created = True
|
|
17
|
-
|
|
18
|
-
def get_content_type_lookup(self, alias, remote_alias):
|
|
19
|
-
field = self.remote_field.model._meta.get_field(self.content_type_field_name)
|
|
20
|
-
return field.get_lookup("in")(
|
|
21
|
-
field.get_col(remote_alias), get_descendants_content_types_pks(self.model)
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
def get_object_id_lookup(self, alias, remote_alias):
|
|
25
|
-
from_field = self.remote_field.model._meta.get_field(self.object_id_field_name)
|
|
26
|
-
to_field = self.model._meta.pk
|
|
27
|
-
return from_field.get_lookup("exact")(
|
|
28
|
-
from_field.get_col(remote_alias), Cast(to_field.get_col(alias), from_field)
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
def get_extra_restriction(self, alias, remote_alias):
|
|
32
|
-
cond = WhereNode()
|
|
33
|
-
cond.add(self.get_content_type_lookup(alias, remote_alias), "AND")
|
|
34
|
-
cond.add(self.get_object_id_lookup(alias, remote_alias), "AND")
|
|
35
|
-
return cond
|
|
36
|
-
|
|
37
|
-
def resolve_related_fields(self):
|
|
38
|
-
return []
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class BaseIndexEntry(models.Model):
|
|
13
|
+
class IndexEntry(AbstractIndexEntry):
|
|
42
14
|
"""
|
|
43
|
-
|
|
44
|
-
It should be extended by the models specific for each backend.
|
|
15
|
+
The IndexEntry model that will get created in the database.
|
|
45
16
|
"""
|
|
46
17
|
|
|
47
|
-
|
|
48
|
-
ContentType, on_delete=models.CASCADE, related_name="+"
|
|
49
|
-
)
|
|
50
|
-
# We do not use an IntegerField since primary keys are not always integers.
|
|
51
|
-
object_id = models.CharField(max_length=50)
|
|
52
|
-
content_object = GenericForeignKey()
|
|
53
|
-
|
|
54
|
-
# TODO: Add per-object boosting.
|
|
55
|
-
# This field stores the "Title Normalisation Factor"
|
|
56
|
-
# This factor is multiplied onto the rank of the title field.
|
|
57
|
-
# This allows us to apply a boost to results with shorter titles
|
|
58
|
-
# elevating more specific matches to the top.
|
|
59
|
-
title_norm = models.FloatField(default=1.0)
|
|
60
|
-
|
|
61
|
-
wagtail_reference_index_ignore = True
|
|
62
|
-
|
|
63
|
-
class Meta:
|
|
64
|
-
unique_together = ("content_type", "object_id")
|
|
65
|
-
verbose_name = _("index entry")
|
|
66
|
-
verbose_name_plural = _("index entries")
|
|
67
|
-
abstract = True
|
|
68
|
-
|
|
69
|
-
def __str__(self):
|
|
70
|
-
return f"{self.content_type.name}: {self.content_object}"
|
|
71
|
-
|
|
72
|
-
@property
|
|
73
|
-
def model(self):
|
|
74
|
-
return self.content_type.model
|
|
75
|
-
|
|
76
|
-
@classmethod
|
|
77
|
-
def add_generic_relations(cls):
|
|
78
|
-
for model in apps.get_models():
|
|
79
|
-
if class_is_indexed(model):
|
|
80
|
-
TextIDGenericRelation(cls).contribute_to_class(model, "index_entries")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
# AbstractIndexEntry will be defined depending on which database system we're using.
|
|
84
|
-
if connection.vendor == "postgresql":
|
|
85
|
-
from django.contrib.postgres.indexes import GinIndex
|
|
86
|
-
from django.contrib.postgres.search import SearchVectorField
|
|
87
|
-
|
|
88
|
-
class AbstractPostgresIndexEntry(BaseIndexEntry):
|
|
89
|
-
"""
|
|
90
|
-
This class is the specific IndexEntry model for PostgreSQL database systems.
|
|
91
|
-
It inherits the fields defined in BaseIndexEntry, and adds PostgreSQL-specific
|
|
92
|
-
fields (tsvectors), plus indexes for doing full-text search on those fields.
|
|
93
|
-
"""
|
|
94
|
-
|
|
95
|
-
# TODO: Add per-object boosting.
|
|
96
|
-
autocomplete = SearchVectorField()
|
|
97
|
-
title = SearchVectorField()
|
|
98
|
-
body = SearchVectorField()
|
|
99
|
-
|
|
100
|
-
class Meta(BaseIndexEntry.Meta):
|
|
101
|
-
abstract = True
|
|
102
|
-
# An additional computed GIN index on 'title || body' is created in a SQL migration
|
|
103
|
-
# covers the default case of PostgresSearchQueryCompiler.get_index_vectors.
|
|
104
|
-
indexes = [
|
|
105
|
-
GinIndex(fields=["autocomplete"]),
|
|
106
|
-
GinIndex(fields=["title"]),
|
|
107
|
-
GinIndex(fields=["body"]),
|
|
108
|
-
]
|
|
109
|
-
|
|
110
|
-
AbstractIndexEntry = AbstractPostgresIndexEntry
|
|
111
|
-
|
|
112
|
-
elif connection.vendor == "sqlite":
|
|
113
|
-
from wagtail.search.backends.database.sqlite.utils import fts5_available
|
|
114
|
-
|
|
115
|
-
class AbstractSQLiteIndexEntry(BaseIndexEntry):
|
|
18
|
+
class Meta(AbstractIndexEntry.Meta):
|
|
116
19
|
"""
|
|
117
|
-
|
|
20
|
+
Contains everything in the AbstractIndexEntry Meta class, but makes this model concrete.
|
|
118
21
|
"""
|
|
119
22
|
|
|
120
|
-
|
|
121
|
-
title = TextField(null=False)
|
|
122
|
-
body = TextField(null=True)
|
|
123
|
-
|
|
124
|
-
class Meta(BaseIndexEntry.Meta):
|
|
125
|
-
abstract = True
|
|
126
|
-
|
|
127
|
-
AbstractIndexEntry = AbstractSQLiteIndexEntry
|
|
128
|
-
|
|
129
|
-
if fts5_available():
|
|
130
|
-
|
|
131
|
-
class SQLiteFTSIndexEntry(models.Model):
|
|
132
|
-
autocomplete = TextField(null=True)
|
|
133
|
-
title = TextField(null=False)
|
|
134
|
-
body = TextField(null=True)
|
|
135
|
-
index_entry = OneToOneField(
|
|
136
|
-
primary_key=True,
|
|
137
|
-
to="wagtailsearch.indexentry",
|
|
138
|
-
on_delete=models.CASCADE,
|
|
139
|
-
db_column="rowid",
|
|
140
|
-
)
|
|
23
|
+
abstract = False
|
|
141
24
|
|
|
142
|
-
class Meta:
|
|
143
|
-
db_table = "wagtailsearch_indexentry_fts"
|
|
144
25
|
|
|
145
|
-
|
|
26
|
+
if AbstractSQLiteFTSIndexEntry:
|
|
27
|
+
# The SQLite backend additionally requires a second model with a OneToOneField to IndexEntry. If a
|
|
28
|
+
# SQLite connection is in use, modelsearch will define a AbstractSQLiteFTSIndexEntry model
|
|
29
|
+
# (otherwise this will be None).
|
|
146
30
|
|
|
147
|
-
class
|
|
31
|
+
class SQLiteFTSIndexEntry(AbstractSQLiteFTSIndexEntry):
|
|
148
32
|
"""
|
|
149
|
-
|
|
33
|
+
The SQLite FTS IndexEntry model that will get created in the database if using SQLite with FTS5 support.
|
|
150
34
|
"""
|
|
151
35
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
AbstractIndexEntry = AbstractMySQLIndexEntry
|
|
160
|
-
|
|
161
|
-
else:
|
|
162
|
-
AbstractIndexEntry = BaseIndexEntry
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
class IndexEntry(AbstractIndexEntry):
|
|
166
|
-
"""
|
|
167
|
-
The IndexEntry model that will get created in the database.
|
|
168
|
-
"""
|
|
36
|
+
index_entry = OneToOneField(
|
|
37
|
+
primary_key=True,
|
|
38
|
+
to=IndexEntry,
|
|
39
|
+
on_delete=models.CASCADE,
|
|
40
|
+
db_column="rowid",
|
|
41
|
+
)
|
|
169
42
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
43
|
+
class Meta(AbstractSQLiteFTSIndexEntry.Meta):
|
|
44
|
+
"""
|
|
45
|
+
Contains everything in the AbstractSQLiteFTSIndexEntry Meta class, but makes this model concrete.
|
|
46
|
+
"""
|
|
174
47
|
|
|
175
|
-
|
|
48
|
+
abstract = False
|
|
49
|
+
db_table = "wagtailsearch_indexentry_fts"
|
wagtail/search/query.py
CHANGED
|
@@ -1,114 +1 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Base classes
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class SearchQuery:
|
|
7
|
-
def __and__(self, other):
|
|
8
|
-
return And([self, other])
|
|
9
|
-
|
|
10
|
-
def __or__(self, other):
|
|
11
|
-
return Or([self, other])
|
|
12
|
-
|
|
13
|
-
def __invert__(self):
|
|
14
|
-
return Not(self)
|
|
15
|
-
|
|
16
|
-
def __repr__(self):
|
|
17
|
-
raise NotImplementedError
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
#
|
|
21
|
-
# Basic query classes
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class PlainText(SearchQuery):
|
|
26
|
-
OPERATORS = ["and", "or"]
|
|
27
|
-
DEFAULT_OPERATOR = "and"
|
|
28
|
-
|
|
29
|
-
def __init__(
|
|
30
|
-
self, query_string: str, operator: str = DEFAULT_OPERATOR, boost: float = 1
|
|
31
|
-
):
|
|
32
|
-
self.query_string = query_string
|
|
33
|
-
self.operator = operator.lower()
|
|
34
|
-
if self.operator not in self.OPERATORS:
|
|
35
|
-
raise ValueError("`operator` must be either 'or' or 'and'.")
|
|
36
|
-
self.boost = boost
|
|
37
|
-
|
|
38
|
-
def __repr__(self):
|
|
39
|
-
return "<PlainText {} operator={} boost={}>".format(
|
|
40
|
-
repr(self.query_string), repr(self.operator), repr(self.boost)
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
class Phrase(SearchQuery):
|
|
45
|
-
def __init__(self, query_string: str):
|
|
46
|
-
self.query_string = query_string
|
|
47
|
-
|
|
48
|
-
def __repr__(self):
|
|
49
|
-
return f"<Phrase {repr(self.query_string)}>"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class Fuzzy(SearchQuery):
|
|
53
|
-
OPERATORS = ["and", "or"]
|
|
54
|
-
DEFAULT_OPERATOR = "or"
|
|
55
|
-
|
|
56
|
-
def __init__(self, query_string: str, operator: str = DEFAULT_OPERATOR):
|
|
57
|
-
self.query_string = query_string
|
|
58
|
-
self.operator = operator.lower()
|
|
59
|
-
if self.operator not in self.OPERATORS:
|
|
60
|
-
raise ValueError("`operator` must be either 'or' or 'and'.")
|
|
61
|
-
|
|
62
|
-
def __repr__(self):
|
|
63
|
-
return f"<Fuzzy {repr(self.query_string)} operator={repr(self.operator)}>"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class MatchAll(SearchQuery):
|
|
67
|
-
def __repr__(self):
|
|
68
|
-
return "<MatchAll>"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class Boost(SearchQuery):
|
|
72
|
-
def __init__(self, subquery: SearchQuery, boost: float):
|
|
73
|
-
self.subquery = subquery
|
|
74
|
-
self.boost = boost
|
|
75
|
-
|
|
76
|
-
def __repr__(self):
|
|
77
|
-
return f"<Boost {repr(self.subquery)} boost={repr(self.boost)}>"
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
#
|
|
81
|
-
# Combinators
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
class And(SearchQuery):
|
|
86
|
-
def __init__(self, subqueries):
|
|
87
|
-
self.subqueries = subqueries
|
|
88
|
-
|
|
89
|
-
def __repr__(self):
|
|
90
|
-
return "<And {}>".format(
|
|
91
|
-
" ".join(repr(subquery) for subquery in self.subqueries)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class Or(SearchQuery):
|
|
96
|
-
def __init__(self, subqueries):
|
|
97
|
-
self.subqueries = subqueries
|
|
98
|
-
|
|
99
|
-
def __repr__(self):
|
|
100
|
-
return "<Or {}>".format(
|
|
101
|
-
" ".join(repr(subquery) for subquery in self.subqueries)
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
class Not(SearchQuery):
|
|
106
|
-
def __init__(self, subquery: SearchQuery):
|
|
107
|
-
self.subquery = subquery
|
|
108
|
-
|
|
109
|
-
def __repr__(self):
|
|
110
|
-
return f"<Not {repr(self.subquery)}>"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
MATCH_ALL = MatchAll()
|
|
114
|
-
MATCH_NONE = Not(MATCH_ALL)
|
|
1
|
+
from wagtailmodelsearch.query import * # noqa: F403
|
wagtail/search/queryset.py
CHANGED
|
@@ -1,43 +1 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class SearchableQuerySetMixin:
|
|
5
|
-
def search(
|
|
6
|
-
self,
|
|
7
|
-
query,
|
|
8
|
-
fields=None,
|
|
9
|
-
operator=None,
|
|
10
|
-
order_by_relevance=True,
|
|
11
|
-
backend="default",
|
|
12
|
-
):
|
|
13
|
-
"""
|
|
14
|
-
This runs a search query on all the items in the QuerySet
|
|
15
|
-
"""
|
|
16
|
-
search_backend = get_search_backend(backend)
|
|
17
|
-
return search_backend.search(
|
|
18
|
-
query,
|
|
19
|
-
self,
|
|
20
|
-
fields=fields,
|
|
21
|
-
operator=operator,
|
|
22
|
-
order_by_relevance=order_by_relevance,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
def autocomplete(
|
|
26
|
-
self,
|
|
27
|
-
query,
|
|
28
|
-
fields=None,
|
|
29
|
-
operator=None,
|
|
30
|
-
order_by_relevance=True,
|
|
31
|
-
backend="default",
|
|
32
|
-
):
|
|
33
|
-
"""
|
|
34
|
-
This runs an autocomplete query on all the items in the QuerySet
|
|
35
|
-
"""
|
|
36
|
-
search_backend = get_search_backend(backend)
|
|
37
|
-
return search_backend.autocomplete(
|
|
38
|
-
query,
|
|
39
|
-
self,
|
|
40
|
-
fields=fields,
|
|
41
|
-
operator=operator,
|
|
42
|
-
order_by_relevance=order_by_relevance,
|
|
43
|
-
)
|
|
1
|
+
from wagtailmodelsearch.queryset import * # noqa: F403
|
|
@@ -1,24 +1 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
from . import index
|
|
4
|
-
from .tasks import insert_or_update_object_task
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def post_save_signal_handler(instance, **kwargs):
|
|
8
|
-
insert_or_update_object_task.enqueue(
|
|
9
|
-
instance._meta.app_label, instance._meta.model_name, str(instance.pk)
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def post_delete_signal_handler(instance, **kwargs):
|
|
14
|
-
index.remove_object(instance)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def register_signal_handlers():
|
|
18
|
-
# Loop through list and register signal handlers for each one
|
|
19
|
-
for model in index.get_indexed_models():
|
|
20
|
-
if not getattr(model, "search_auto_update", True):
|
|
21
|
-
continue
|
|
22
|
-
|
|
23
|
-
post_save.connect(post_save_signal_handler, sender=model)
|
|
24
|
-
post_delete.connect(post_delete_signal_handler, sender=model)
|
|
1
|
+
from wagtailmodelsearch.signal_handlers import * # noqa: F403
|
wagtail/search/tasks.py
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
from
|
|
2
|
-
from django_tasks import task
|
|
3
|
-
|
|
4
|
-
from wagtail.search import index
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@task()
|
|
8
|
-
def insert_or_update_object_task(app_label, model_name, pk):
|
|
9
|
-
model = apps.get_model(app_label, model_name)
|
|
10
|
-
index.insert_or_update_object(model.objects.get(pk=pk))
|
|
1
|
+
from wagtailmodelsearch.tasks import * # noqa: F403
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from django.conf import settings
|
|
4
|
+
from django.test import TestCase
|
|
5
|
+
|
|
6
|
+
from wagtail.search.backends import get_search_backend
|
|
7
|
+
from wagtail.utils.deprecation import RemovedInWagtail80Warning
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@unittest.skipIf(
|
|
11
|
+
"elasticsearch_with_index_option" not in settings.WAGTAILSEARCH_BACKENDS,
|
|
12
|
+
"No elasticsearch backend active",
|
|
13
|
+
)
|
|
14
|
+
class TestIndexOptionDeprecation(TestCase):
|
|
15
|
+
def test_index_option_deprecation_warning(self):
|
|
16
|
+
with self.assertWarnsMessage(
|
|
17
|
+
RemovedInWagtail80Warning,
|
|
18
|
+
"The INDEX option on Elasticsearch / OpenSearch backends is deprecated",
|
|
19
|
+
):
|
|
20
|
+
backend = get_search_backend("elasticsearch_with_index_option")
|
|
21
|
+
|
|
22
|
+
self.assertEqual(backend.index_prefix, "wagtailtest_")
|