moviewyrm/bookwyrm/views/search.py

79 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-03-08 16:49:10 +00:00
""" search users or books """
2021-01-13 20:03:27 +00:00
def get(self, request):
2021-03-08 16:49:10 +00:00
""" that search bar up top """
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)
# use webfinger for mastodon style account@domain.com username
2021-03-08 16:49:10 +00:00
if re.match(r"\B%s" % regex.full_username, query):
2021-01-13 20:03:27 +00:00
handle_remote_webfinger(query)
2021-02-01 19:50:47 +00:00
# do a user search
2021-03-08 16:49:10 +00:00
user_results = (
models.User.viewer_aware_objects(request.user)
.annotate(
similarity=Greatest(
TrigramSimilarity("username", query),
TrigramSimilarity("localname", query),
)
)
.filter(
similarity__gt=0.5,
2021-01-13 20:03:27 +00:00
)
2021-03-08 16:49:10 +00:00
.order_by("-similarity")[:10]
)
2021-01-13 20:03:27 +00:00
2021-02-01 19:50:47 +00:00
# any relevent lists?
2021-03-08 16:49:10 +00:00
list_results = (
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
2021-03-08 16:49:10 +00:00
book_results = connector_manager.search(query, min_confidence=min_confidence)
2021-01-13 20:03:27 +00:00
data = {
2021-03-08 16:49:10 +00:00
"book_results": book_results,
"user_results": user_results,
"list_results": list_results,
"query": query,
2021-01-13 20:03:27 +00:00
}
2021-03-08 16:49:10 +00:00
return TemplateResponse(request, "search_results.html", data)