forked from Siege-Software/django-typesense
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadmin.py
162 lines (134 loc) · 4.99 KB
/
admin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import logging
from django.contrib import admin
from django.contrib.auth.admin import csrf_protect_m
from django.db.models import QuerySet
from django.forms import forms
from django.http import JsonResponse
from django_typesense.paginator import TypesenseSearchPaginator
from django_typesense.utils import typesense_search
logger = logging.getLogger(__name__)
class TypesenseSearchAdminMixin(admin.ModelAdmin):
typesense_search_fields = []
def get_typesense_search_fields(self, request):
"""Return a sequence containing the fields to
be searched wheneversomebody submits a search query.
"""
return self.typesense_search_fields
@property
def media(self):
super_media = super().media
return forms.Media(
js=super_media._js + ["admin/js/search-typesense.js"],
css=super_media._css,
)
@csrf_protect_m
def changelist_view(self, request, extra_context=None):
"""The 'change list' admin view for this model."""
template_response = super().changelist_view(request, extra_context)
is_ajax = request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"
if is_ajax:
html = template_response.render().rendered_content
return JsonResponse(data={"html": html}, safe=False)
return template_response
def get_sortable_by(self, request):
"""Get sortable fields; these are fields that sort is defaulted or set to True.
Parameters
----------
request: HttpRequest
The current request object.
Returns
-------
list
A list of field names
"""
sortable_fields = super().get_sortable_by(request)
return set(sortable_fields).intersection(
self.model.collection_class.sortable_fields
)
def get_results(self, request):
"""Get all indexed data without any filtering or specific
search terms. Works like `ModelAdmin.get_queryset()`.
Parameters
----------
request: HttpRequest
The current request object.
Returns
-------
list
A list of the typesense results
"""
return typesense_search(
collection_name=self.model.collection_class.schema_name,
q="*",
query_by=self.model.collection_class.query_by_fields,
)
def get_changelist(self, request, **kwargs):
"""Return the ChangeList class for use on the changelist page."""
from django_typesense.changelist import TypesenseChangeList
return TypesenseChangeList
def get_paginator(
self, request, results, per_page, orphans=0, allow_empty_first_page=True
):
# fallback incase we receive a queryset.
if isinstance(results, QuerySet):
return super().get_paginator(
request, results, per_page, orphans, allow_empty_first_page
)
return TypesenseSearchPaginator(
results, per_page, orphans, allow_empty_first_page, self.model
)
def get_typesense_search_results(
self,
request,
search_term: str,
page_num: int = 1,
filter_by: str = "",
sort_by: str = "",
):
"""
Get the results from typesense with the provided filtering,
sorting, pagination and search parameters applied.
Parameters
----------
request: HttpRequest
The current request object.
search_term: str
The search term provided in the search form.
page_num: int
The requested page number.
filter_by: str
The filtering parameters.
sort_by: str
The sort parameters.
Returns
-------
list
A list of typesense results
"""
results = typesense_search(
collection_name=self.model.collection_class.schema_name,
q=search_term or "*",
query_by=self.model.collection_class.query_by_fields,
page=page_num,
per_page=self.list_per_page,
filter_by=filter_by,
sort_by=sort_by,
)
return results
def get_search_results(self, request, queryset, search_term):
if not request.POST.get("action"):
may_have_duplicates = False
results = self.get_typesense_search_results(request, search_term)
ids = [result["document"]["id"] for result in results["hits"]]
queryset = queryset.filter(id__in=ids)
else:
# id_dict_list = export_documents(
# self.model.collection_class.schema_name, include_fields=["id"]
# )
# queryset = queryset.filter(
# id__in=[id_dict["id"] for id_dict in id_dict_list]
# )
queryset, may_have_duplicates = super().get_search_results(
request, queryset, search_term
)
return queryset, may_have_duplicates