Skip to content

Commit 1749cce

Browse files
committed
Rework the search backend
1 parent f6ed037 commit 1749cce

File tree

5 files changed

+35
-90
lines changed

5 files changed

+35
-90
lines changed

api/paul_api/api/permissions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ def has_permission(self, request, view):
105105
checker = ObjectPermissionChecker(user)
106106
user_perms = checker.get_perms(table)
107107

108-
READ_ACTIONS = ['csv_export', 'xlsx_export']
108+
READ_ACTIONS = ["csv_export", "xlsx_export", "search"]
109109

110-
if view.action in READ_ACTIONS and 'view_table' in user_perms:
110+
if view.action in READ_ACTIONS and "view_table" in user_perms:
111111
return True
112112

113113
return False

api/paul_api/api/serializers/entries.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,6 @@ def __init__(self, *args, **kwargs):
5454
self.fields[field_name] = MappedField(source="data.{}".format(field_name), required=False)
5555

5656

57-
class EntryReadSerializer(serializers.ModelSerializer):
58-
class Meta:
59-
model = Entry
60-
fields = ["url", "id", "table", "date_created", "data"]
61-
62-
def get_url(self, obj):
63-
return self.context["request"].build_absolute_uri(
64-
reverse(
65-
"table-entries-detail",
66-
kwargs={"pk": obj.pk, "table_pk": obj.table.pk},
67-
)
68-
)
69-
70-
7157
class EntrySerializer(serializers.ModelSerializer):
7258
url = serializers.SerializerMethodField()
7359
data = serializers.SerializerMethodField()

api/paul_api/api/serializers/tables.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,7 @@ def get_current_user_permissions(self, obj: Table) -> List[str]:
235235
table_permissions.append("")
236236
return table_permissions
237237

238+
239+
class TableSearchCountSerializer(serializers.Serializer):
240+
table = serializers.IntegerField()
241+
total = serializers.IntegerField()

api/paul_api/api/urls.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
router.register(r"csv-imports", views.CsvImportViewSet)
1818
router.register(r"charts", views.ChartViewSet)
1919
router.register(r"cards", views.CardViewSet)
20-
router.register(r"entries", views.EntryGlobalViewSet)
2120
router.register(r"tablelinks", views.TableLinkViewSet)
2221

2322
tables_router = routers.NestedSimpleRouter(router, "tables", lookup="table")

api/paul_api/api/views.py

Lines changed: 29 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.core.paginator import Paginator
66
from django.contrib.auth.models import Group, User
77
from django.conf import settings
8-
from django.db.models import Q
8+
from django.db.models import Q, Count
99
from django.http import HttpResponse, Http404
1010
from django.utils.translation import gettext_lazy as _
1111
from django_filters import rest_framework as filters
@@ -176,6 +176,8 @@ def get_permissions(self):
176176
base_permissions = super(self.__class__, self).get_permissions()
177177
if self.action in ["csv_export", "xlsx_export"]:
178178
base_permissions = (TableCustomActionPermissions(),)
179+
elif self.action in ["search"]:
180+
base_permissions = ()
179181
return base_permissions
180182

181183
def create(self, request):
@@ -280,6 +282,27 @@ def create_contacts_table(self, request):
280282
}
281283
return Response(response_data)
282284

285+
@action(
286+
detail=False,
287+
methods=["get"],
288+
name=_("Find tables containing text"),
289+
url_path="search",
290+
)
291+
def search(self, request):
292+
needle = request.GET.get("query").strip()
293+
tables = models.Table.objects.all()
294+
table_ids = []
295+
for table in tables:
296+
# TODO: check table view permissions
297+
table_ids.append(table.id)
298+
299+
queryset = models.Entry.objects.filter(
300+
table__id__in=table_ids, data__icontains=needle
301+
).all().values("table").annotate(total=Count("table")).order_by("table")
302+
303+
serializer = serializers.tables.TableSearchCountSerializer(queryset, many=True)
304+
return Response(serializer.data)
305+
283306
@action(
284307
detail=True,
285308
methods=["post"],
@@ -1046,78 +1069,6 @@ def csv_export(self, request, pk):
10461069
return response
10471070

10481071

1049-
class EntryGlobalViewSet(viewsets.ModelViewSet):
1050-
queryset = models.Entry.objects.all().order_by("id")
1051-
pagination_class = EntriesPagination
1052-
serializer_class = serializers.entries.EntryReadSerializer
1053-
# filter_backends = (drf_filters.SearchFilter, )
1054-
# search_fields = ("data", )
1055-
# # permission_classes = (TableEntryPermissions, )
1056-
1057-
# def list(self, request):
1058-
# page = self.paginate_queryset(self.queryset)
1059-
1060-
# if page is not None:
1061-
# serializer = serializers.entries.EntryReadSerializer(
1062-
# page,
1063-
# many=True,
1064-
# context={"request": request},
1065-
# )
1066-
# return self.get_paginated_response(serializer.data)
1067-
# serializer = serializers.entries.EntryReadSerializer(self.queryset, many=True)
1068-
# return Response(serializer.data)
1069-
1070-
def list(self, request):
1071-
return Http404
1072-
1073-
def create(self, request):
1074-
return Http404
1075-
1076-
def retrieve(self, request, pk=None):
1077-
return Http404
1078-
1079-
def update(self, request, pk=None):
1080-
return Http404
1081-
1082-
def partial_update(self, request, pk=None):
1083-
return Http404
1084-
1085-
def destroy(self, request, pk=None):
1086-
return Http404
1087-
1088-
@action(
1089-
detail=False,
1090-
methods=["get"],
1091-
url_name="search",
1092-
url_path="search",
1093-
)
1094-
def search(self, request):
1095-
""" Text search over the entries """
1096-
1097-
needle = request.GET.get("query")
1098-
1099-
tables = models.Table.objects.all()
1100-
table_ids = []
1101-
for table in tables:
1102-
# TODO: apply permissions
1103-
table_ids.append(table.id)
1104-
1105-
queryset = models.Entry.objects.filter(
1106-
table__id__in=table_ids, data__icontains=needle).order_by("id")
1107-
page = self.paginate_queryset(queryset)
1108-
1109-
if page is not None:
1110-
serializer = serializers.entries.EntryReadSerializer(
1111-
page,
1112-
many=True,
1113-
context={"request": request},
1114-
)
1115-
return self.get_paginated_response(serializer.data)
1116-
1117-
serializer = serializers.entries.EntryReadSerializer(queryset, many=True)
1118-
return Response(serializer.data)
1119-
1120-
11211072
class EntryViewSet(viewsets.ModelViewSet):
11221073
pagination_class = EntriesPagination
11231074
serializer_class = serializers.entries.EntrySerializer
@@ -1133,6 +1084,7 @@ def list(self, request, table_pk):
11331084

11341085
str_fields = request.GET.get("__fields", "") if request else None
11351086
str_order = request.GET.get("__order", "") if request else None
1087+
str_search = request.GET.get("search", "").strip() if request else None
11361088
table_fields = {x.name: x.field_type for x in table.fields.all().order_by("id")}
11371089
default_fields = {x.name: x for x in table.default_fields.all().order_by("id")}
11381090

@@ -1158,6 +1110,10 @@ def list(self, request, table_pk):
11581110
queryset = table.entries.filter(filter_dict).order_by("id")
11591111
# queryset = table.entries.annotate(date_field=Cast(KeyTextTransform('data_iesire', "data"), DateField())).filter(date_field__exact='2020-07-21').order_by("id")
11601112

1113+
# simple text search over the entire data field
1114+
if str_search:
1115+
queryset = queryset.filter(data__icontains=str_search)
1116+
11611117
page = self.paginate_queryset(queryset)
11621118

11631119
if page is not None:

0 commit comments

Comments
 (0)