moviewyrm/bookwyrm/views/search.py

78 lines
2.5 KiB
Python
Raw Normal View History

2021-03-08 16:49:10 +00:00
""" search views"""
2021-01-13 20:03:27 +00:00
import re
from django.contrib.postgres.search import TrigramSimilarity
from django.db.models.functions import Greatest
from django.http import JsonResponse
from django.template.response import TemplateResponse
from django.views import View
from bookwyrm import models
from bookwyrm.connectors import connector_manager
from bookwyrm.utils import regex
2021-02-01 19:50:47 +00:00
from .helpers import is_api_request, privacy_filter
2021-01-13 20:03:27 +00:00
from .helpers import handle_remote_webfinger
# pylint: disable= no-self-use
class Search(View):
2021-04-26 16:15:42 +00:00
"""search users or books"""
2021-03-08 16:49:10 +00:00
2021-01-13 20:03:27 +00:00
def get(self, request):
2021-04-26 16:15:42 +00:00
"""that search bar up top"""
2021-03-08 16:49:10 +00:00
query = request.GET.get("q")
min_confidence = request.GET.get("min_confidence", 0.1)
2021-01-13 20:03:27 +00:00
if is_api_request(request):
# only return local book results via json so we don't cascade
book_results = connector_manager.local_search(
2021-03-08 16:49:10 +00:00
query, min_confidence=min_confidence
)
2021-01-13 20:03:27 +00:00
return JsonResponse([r.json() for r in book_results], safe=False)
data = {"query": query or ""}
2021-01-13 20:03:27 +00:00
# use webfinger for mastodon style account@domain.com username
2021-03-31 19:03:58 +00:00
if query and re.match(regex.full_username, query):
2021-01-13 20:03:27 +00:00
handle_remote_webfinger(query)
2021-04-08 16:59:21 +00:00
# do a user search
if request.user.is_authenticated:
data["user_results"] = (
models.User.viewer_aware_objects(request.user)
.annotate(
similarity=Greatest(
TrigramSimilarity("username", query),
TrigramSimilarity("localname", query),
)
2021-03-08 16:49:10 +00:00
)
.filter(
similarity__gt=0.5,
)
.order_by("-similarity")[:10]
2021-03-08 16:49:10 +00:00
)
2021-01-13 20:03:27 +00:00
2021-02-01 19:50:47 +00:00
# any relevent lists?
data["list_results"] = (
2021-03-08 16:49:10 +00:00
privacy_filter(
request.user,
models.List.objects,
privacy_levels=["public", "followers"],
)
.annotate(
similarity=Greatest(
TrigramSimilarity("name", query),
TrigramSimilarity("description", query),
)
)
.filter(
similarity__gt=0.1,
2021-02-01 19:50:47 +00:00
)
2021-03-08 16:49:10 +00:00
.order_by("-similarity")[:10]
)
2021-02-01 19:50:47 +00:00
data["book_results"] = connector_manager.search(
query, min_confidence=min_confidence
)
2021-03-08 16:49:10 +00:00
return TemplateResponse(request, "search_results.html", data)