kopia lustrzana https://github.com/wagtail/wagtail
Allow customising the search_fields and search backend to use via SnippetViewSet (#10290)
rodzic
3965ceedfa
commit
167471b1f7
|
@ -40,6 +40,7 @@ Changelog
|
|||
* Allow overriding the base queryset to be used in snippet `IndexView` (Sage Abdullah)
|
||||
* Revise alignment and spacing of form fields and sections (Thibaud Colas)
|
||||
* Update Wagtail’s type scale so StreamField block labels and field labels are the same size (Thibaud Colas)
|
||||
* Allow customising the `search_fields` and search backend via SnippetViewSet (Sage Abdullah)
|
||||
* Fix: Ensure `label_format` on StructBlock gracefully handles missing variables (Aadi jindal)
|
||||
* Fix: Adopt a no-JavaScript and more accessible solution for the 'Reset to default' switch to Gravatar when editing user profile (Loveth Omokaro)
|
||||
* Fix: Ensure `Site.get_site_root_paths` works on cache backends that do not preserve Python objects (Jaap Roes)
|
||||
|
|
|
@ -83,6 +83,8 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
|
|||
.. autoattribute:: list_display
|
||||
.. autoattribute:: list_filter
|
||||
.. autoattribute:: filterset_class
|
||||
.. autoattribute:: search_fields
|
||||
.. autoattribute:: search_backend_name
|
||||
.. autoattribute:: list_per_page
|
||||
.. autoattribute:: ordering
|
||||
.. autoattribute:: admin_url_namespace
|
||||
|
|
|
@ -79,6 +79,7 @@ Those improvements were implemented by Albina Starykova as part of an [Outreachy
|
|||
* Allow overriding the base queryset to be used in snippet `IndexView` (Sage Abdullah)
|
||||
* Revise alignment and spacing of form fields and sections (Thibaud Colas)
|
||||
* Update Wagtail’s type scale so StreamField block labels and field labels are the same size (Thibaud Colas)
|
||||
* Allow customising the `search_fields` and search backend via SnippetViewSet (Sage Abdullah)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ class IndexView(
|
|||
page_kwarg = "p"
|
||||
default_ordering = None
|
||||
search_fields = None
|
||||
search_backend_name = "default"
|
||||
is_searchable = None
|
||||
search_kwarg = "q"
|
||||
filters = None
|
||||
|
@ -258,8 +259,8 @@ class IndexView(
|
|||
if not self.search_query:
|
||||
return queryset
|
||||
|
||||
if class_is_indexed(queryset.model):
|
||||
search_backend = get_search_backend()
|
||||
if class_is_indexed(queryset.model) and self.search_backend_name:
|
||||
search_backend = get_search_backend(self.search_backend_name)
|
||||
return search_backend.search(
|
||||
self.search_query, queryset, fields=self.search_fields
|
||||
)
|
||||
|
|
|
@ -745,3 +745,71 @@ class TestCustomOrdering(BaseSnippetViewSetTests):
|
|||
"DDDDDDDDDD",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TestDjangoORMSearchBackend(BaseSnippetViewSetTests):
|
||||
model = DraftStateModel
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.first = cls.model.objects.create(
|
||||
text="Wagtail is a Django-based CMS",
|
||||
)
|
||||
cls.second = cls.model.objects.create(
|
||||
text="Django is a Python-based web framework",
|
||||
)
|
||||
cls.third = cls.model.objects.create(
|
||||
text="Python is a programming-bas, uh, language",
|
||||
)
|
||||
|
||||
def get(self, params={}):
|
||||
return self.client.get(self.get_url("list"), params)
|
||||
|
||||
def test_simple(self):
|
||||
response = self.get()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailsnippets/snippets/index.html")
|
||||
|
||||
# All objects should be in items
|
||||
self.assertCountEqual(
|
||||
list(response.context["page_obj"].object_list),
|
||||
[self.first, self.second, self.third],
|
||||
)
|
||||
|
||||
# The search box should not raise an error
|
||||
self.assertNotContains(response, "This field is required.")
|
||||
|
||||
def test_empty_q(self):
|
||||
response = self.get({"q": ""})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailsnippets/snippets/index.html")
|
||||
|
||||
# All objects should be in items
|
||||
self.assertCountEqual(
|
||||
list(response.context["page_obj"].object_list),
|
||||
[self.first, self.second, self.third],
|
||||
)
|
||||
|
||||
# The search box should not raise an error
|
||||
self.assertNotContains(response, "This field is required.")
|
||||
|
||||
def test_is_searchable(self):
|
||||
self.assertTrue(self.get().context["is_searchable"])
|
||||
|
||||
def test_search_one(self):
|
||||
response = self.get({"q": "Django"})
|
||||
|
||||
# Only objects with "Django" should be in items
|
||||
self.assertCountEqual(
|
||||
list(response.context["page_obj"].object_list),
|
||||
[self.first, self.second],
|
||||
)
|
||||
|
||||
def test_search_the(self):
|
||||
response = self.get({"q": "Python"})
|
||||
|
||||
# Only objects with "Python" should be in items
|
||||
self.assertCountEqual(
|
||||
list(response.context["page_obj"].object_list),
|
||||
[self.second, self.third],
|
||||
)
|
||||
|
|
|
@ -647,6 +647,15 @@ class SnippetViewSet(ModelViewSet):
|
|||
#: The default ordering to use for the index view. Can be a string or a list/tuple in the same format as Django's :attr:`~django.db.models.Options.ordering`.
|
||||
ordering = None
|
||||
|
||||
#: The fields to use for the search in the index view.
|
||||
#: If set to ``None`` and :attr:`search_backend_name` is set to use a Wagtail search backend,
|
||||
#: the ``search_fields`` attribute of the model will be used instead.
|
||||
search_fields = None
|
||||
|
||||
#: The name of the Wagtail search backend to use for the search in the index view.
|
||||
#: If set to a falsy value, the search will fall back to use Django's QuerySet API.
|
||||
search_backend_name = "default"
|
||||
|
||||
#: The URL namespace to use for the admin views.
|
||||
#: If left unset, ``wagtailsnippets_{app_label}_{model_name}`` is used instead.
|
||||
admin_url_namespace = None
|
||||
|
@ -811,6 +820,8 @@ class SnippetViewSet(ModelViewSet):
|
|||
list_filter=self.list_filter,
|
||||
paginate_by=self.list_per_page,
|
||||
default_ordering=self.ordering,
|
||||
search_fields=self.search_fields,
|
||||
search_backend_name=self.search_backend_name,
|
||||
)
|
||||
|
||||
@property
|
||||
|
@ -832,6 +843,8 @@ class SnippetViewSet(ModelViewSet):
|
|||
list_filter=self.list_filter,
|
||||
paginate_by=self.list_per_page,
|
||||
default_ordering=self.ordering,
|
||||
search_fields=self.search_fields,
|
||||
search_backend_name=self.search_backend_name,
|
||||
)
|
||||
|
||||
@property
|
||||
|
|
|
@ -250,6 +250,9 @@ class FullFeaturedSnippetViewSet(SnippetViewSet):
|
|||
index_template_name = "tests/fullfeaturedsnippet_index.html"
|
||||
ordering = ["text", "-_updated_at", "-pk"]
|
||||
|
||||
# TODO: When specific search fields are supported in SQLite FTS (see #10217),
|
||||
# specify search_fields or get_search_fields here
|
||||
|
||||
def get_history_template(self):
|
||||
return "tests/snippet_history.html"
|
||||
|
||||
|
@ -259,6 +262,8 @@ class FullFeaturedSnippetViewSet(SnippetViewSet):
|
|||
|
||||
class DraftStateModelViewSet(SnippetViewSet):
|
||||
list_filter = ["text", "first_published_at"]
|
||||
search_fields = ["text"]
|
||||
search_backend_name = None
|
||||
|
||||
|
||||
class ModeratedModelViewSet(SnippetViewSet):
|
||||
|
|
Ładowanie…
Reference in New Issue