Simple search in api
authorRadek Czajka <rczajka@rczajka.pl>
Tue, 5 Aug 2025 14:21:15 +0000 (16:21 +0200)
committerRadek Czajka <rczajka@rczajka.pl>
Tue, 5 Aug 2025 14:21:15 +0000 (16:21 +0200)
src/api/urls.py
src/search/api/urls.py [new file with mode: 0644]
src/search/api/views.py [new file with mode: 0644]
src/search/views.py

index 38f6192..5b1942c 100644 (file)
@@ -17,7 +17,8 @@ urlpatterns1 = [
     path('me/', views.UserView.as_view()),
     path('', include('catalogue.api.urls2')),
     path('', include('social.api.urls2')),
-    path('', include('bookmarks.api.urls'))
+    path('', include('bookmarks.api.urls')),
+    path('', include('search.api.urls')),
 ]
 
 
diff --git a/src/search/api/urls.py b/src/search/api/urls.py
new file mode 100644 (file)
index 0000000..93ddf6d
--- /dev/null
@@ -0,0 +1,13 @@
+# This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
+#
+from django.urls import path
+from . import views
+
+
+urlpatterns = [
+    path('search/hint/', views.HintView.as_view()),
+    path('search/', views.SearchView.as_view()),
+    path('search/books/', views.BookSearchView.as_view()),
+    path('search/text/', views.TextSearchView.as_view()),
+]
diff --git a/src/search/api/views.py b/src/search/api/views.py
new file mode 100644 (file)
index 0000000..1ce66a9
--- /dev/null
@@ -0,0 +1,33 @@
+# This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
+#
+from rest_framework.generics import ListAPIView
+from rest_framework.response import Response
+from rest_framework.views import APIView
+from search.views import get_hints
+from search.forms import SearchFilters
+
+
+class HintView(APIView):
+    def get(self, request):
+        term = request.query_params.get('q')
+        hints = get_hints(term, request.user)
+        return Response(hints)
+
+
+class SearchView(APIView):
+    def get(self, request):
+        term = self.request.query_params.get('q')
+        f = SearchFilters({'q': term})
+        r = {}
+        if f.is_valid():
+            r = f.results()
+        return Response(r)
+
+class BookSearchView(ListAPIView):
+    def get_queryset(self, request):
+        term = self.request.query_params.get('q')
+
+class TextSearchView(ListAPIView):
+    def get_queryset(self, request):
+        term = self.request.query_params.get('q')
index 459190d..01abfc5 100644 (file)
@@ -24,22 +24,8 @@ def remove_query_syntax_chars(query, replace=' '):
     return query_syntax_chars.sub(replace, query)
 
 
-@cache.never_cache
-def hint(request, mozhint=False, param='term'):
-    prefix = request.GET.get(param, '')
-    if len(prefix) < 2:
-        return JsonResponse([], safe=False)
-
-    prefix = re_escape(' '.join(remove_query_syntax_chars(prefix).split()))
-
-    try:
-        limit = int(request.GET.get('max', ''))
-    except ValueError:
-        limit = 20
-    else:
-        if limit < 1:
-            limit = 20
-
+def get_hints(prefix, user=None, limit=10):
+    if not prefix: return []
     data = []
     if len(data) < limit:
         authors = catalogue.models.Tag.objects.filter(
@@ -53,9 +39,10 @@ def hint(request, mozhint=False, param='term'):
             }
             for author in authors[:limit - len(data)]
         ])
-    if request.user.is_authenticated and len(data) < limit:
+    
+    if user is not None and user.is_authenticated and len(data) < limit:
         tags = social.models.UserList.objects.filter(
-            user=request.user, name__iregex='\m' + prefix).only('name', 'id', 'slug')
+            user=user, name__iregex='\m' + prefix).only('name', 'id', 'slug')
         data.extend([
             {
                 'type': 'set',
@@ -114,6 +101,30 @@ def hint(request, mozhint=False, param='term'):
             }
             for info in infos[:limit - len(data)]
         ])
+    return data
+
+
+@cache.never_cache
+def hint(request, mozhint=False, param='term'):
+    prefix = request.GET.get(param, '')
+    if len(prefix) < 2:
+        return JsonResponse([], safe=False)
+
+    prefix = re_escape(' '.join(remove_query_syntax_chars(prefix).split()))
+
+    try:
+        limit = int(request.GET.get('max', ''))
+    except ValueError:
+        limit = 20
+    else:
+        if limit < 1:
+            limit = 20
+
+    data = get_hints(
+        prefix,
+        user=request.user if request.user.is_authenticated else None,
+        limit=limit
+    )
 
     if mozhint:
         data = [