From d93da4e86d771f88d654339b3563a852dc69c767 Mon Sep 17 00:00:00 2001 From: Ross Chapman Date: Mon, 27 Nov 2023 15:03:59 -0800 Subject: [PATCH] Checkpoint --- bookwyrm/book_search.py | 20 ++++++++----- bookwyrm/settings.py | 2 +- .../templates/shelf/search_my_books_form.html | 25 ++++++++++++++++ bookwyrm/templates/shelf/shelf.html | 1 + bookwyrm/tests/views/test_search.py | 2 +- bookwyrm/views/search.py | 6 ++-- bookwyrm/views/shelf/shelf.py | 29 +++++++++++++------ docker-compose.yml | 2 ++ 8 files changed, 66 insertions(+), 21 deletions(-) create mode 100644 bookwyrm/templates/shelf/search_my_books_form.html diff --git a/bookwyrm/book_search.py b/bookwyrm/book_search.py index ceb228f40..6ab33fd5a 100644 --- a/bookwyrm/book_search.py +++ b/bookwyrm/book_search.py @@ -43,6 +43,7 @@ def search( min_confidence: float = 0, filters: Optional[list[Any]] = None, return_first: bool = False, + books = None ) -> Union[Optional[models.Edition], QuerySet[models.Edition]]: """search your local database""" filters = filters or [] @@ -54,17 +55,16 @@ def search( # first, try searching unique identifiers # unique identifiers never have spaces, title/author usually do if not " " in query: - results = search_identifiers(query, *filters, return_first=return_first) + results = search_identifiers(query, *filters, return_first=return_first, books=books) # if there were no identifier results... if not results: # then try searching title/author results = search_title_author( - query, min_confidence, *filters, return_first=return_first + query, min_confidence, *filters, return_first=return_first, books=books ) return results - def isbn_search(query): """search your local database""" if not query: @@ -98,8 +98,9 @@ def format_search_result(search_result): def search_identifiers( - query, *filters, return_first=False + query, *filters, return_first=False, books=None, ) -> Union[Optional[models.Edition], QuerySet[models.Edition]]: + books = books or models.Edition """tries remote_id, isbn; defined as dedupe fields on the model""" if connectors.maybe_isbn(query): # Oh did you think the 'S' in ISBN stood for 'standard'? @@ -111,7 +112,7 @@ def search_identifiers( for f in models.Edition._meta.get_fields() if hasattr(f, "deduplication_field") and f.deduplication_field ] - results = models.Edition.objects.filter( + results = books.filter( *filters, reduce(operator.or_, (Q(**f) for f in or_filters)) ).distinct() @@ -121,12 +122,17 @@ def search_identifiers( def search_title_author( - query, min_confidence, *filters, return_first=False + query, + min_confidence, + *filters, + return_first=False, + books=None, ) -> QuerySet[models.Edition]: """searches for title and author""" + books = books or models.Edition.objects query = SearchQuery(query, config="simple") | SearchQuery(query, config="english") results = ( - models.Edition.objects.filter(*filters, search_vector=query) + books.filter(*filters, search_vector=query) .annotate(rank=SearchRank(F("search_vector"), query)) .filter(rank__gt=min_confidence) .order_by("-rank") diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 4cecc4df6..49e4e2116 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -140,7 +140,7 @@ TEMPLATES = [ }, ] -LOG_LEVEL = env("LOG_LEVEL", "INFO").upper() +LOG_LEVEL = env("LOG_LEVEL", "DEBUG").upper() # Override aspects of the default handler to our taste # See https://docs.djangoproject.com/en/3.2/topics/logging/#default-logging-configuration # for a reference to the defaults we're overriding diff --git a/bookwyrm/templates/shelf/search_my_books_form.html b/bookwyrm/templates/shelf/search_my_books_form.html new file mode 100644 index 000000000..ca9cd2991 --- /dev/null +++ b/bookwyrm/templates/shelf/search_my_books_form.html @@ -0,0 +1,25 @@ +{% load i18n %} +{% load utilities %} + + diff --git a/bookwyrm/templates/shelf/shelf.html b/bookwyrm/templates/shelf/shelf.html index a2410ef95..b84ae185f 100644 --- a/bookwyrm/templates/shelf/shelf.html +++ b/bookwyrm/templates/shelf/shelf.html @@ -123,6 +123,7 @@ {% endif %} {% endwith %} + {% include 'shelf/search_my_books_form.html' with user=user query=query %} {% if is_self and shelf.id %} diff --git a/bookwyrm/tests/views/test_search.py b/bookwyrm/tests/views/test_search.py index 28f8268e3..021d502f0 100644 --- a/bookwyrm/tests/views/test_search.py +++ b/bookwyrm/tests/views/test_search.py @@ -9,7 +9,7 @@ from django.test import TestCase from django.test.client import RequestFactory from bookwyrm import models, views -from bookwyrm.book_search import SearchResult +from bookwyrm.book_search import SearchResult, search from bookwyrm.settings import DOMAIN from bookwyrm.tests.validate_html import validate_html diff --git a/bookwyrm/views/search.py b/bookwyrm/views/search.py index 743f33f59..f8eddd1a6 100644 --- a/bookwyrm/views/search.py +++ b/bookwyrm/views/search.py @@ -51,7 +51,7 @@ class Search(View): def api_book_search(request): """Return books via API response""" query = request.GET.get("q") - query = isbn_check(query) + query = isbn_check_and_format(query) min_confidence = request.GET.get("min_confidence", 0) # only return local book results via json so we don't cascade book_results = search(query, min_confidence=min_confidence) @@ -64,7 +64,7 @@ def book_search(request): """the real business is elsewhere""" query = request.GET.get("q") # check if query is isbn - query = isbn_check(query) + query = isbn_check_and_format(query) min_confidence = request.GET.get("min_confidence", 0) search_remote = request.GET.get("remote", False) and request.user.is_authenticated @@ -159,7 +159,7 @@ def list_search(request): return TemplateResponse(request, "search/list.html", data) -def isbn_check(query): +def isbn_check_and_format(query): """isbn10 or isbn13 check, if so remove separators""" if query: su_num = re.sub(r"(?<=\d)\D(?=\d|[xX])", "", query) diff --git a/bookwyrm/views/shelf/shelf.py b/bookwyrm/views/shelf/shelf.py index dbbcc2d3a..600dfb731 100644 --- a/bookwyrm/views/shelf/shelf.py +++ b/bookwyrm/views/shelf/shelf.py @@ -1,7 +1,7 @@ """ shelf views """ from collections import namedtuple -from django.db.models import OuterRef, Subquery, F, Max +from django.db.models import OuterRef, Subquery, F, Max, QuerySet from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from django.http import HttpResponseBadRequest @@ -15,6 +15,10 @@ from bookwyrm import forms, models from bookwyrm.activitypub import ActivitypubResponse from bookwyrm.settings import PAGE_LENGTH from bookwyrm.views.helpers import is_api_request, get_user_from_username +from bookwyrm.book_search import search + +import logging +logger = logging.getLogger(__name__) # pylint: disable=no-self-use @@ -32,6 +36,8 @@ class Shelf(View): else: shelves = models.Shelf.privacy_filter(request.user).filter(user=user).all() + shelves_search_query = request.GET.get("shelves_q") + # get the shelf and make sure the logged in user should be able to see it if shelf_identifier: shelf = get_object_or_404(user.shelf_set, identifier=shelf_identifier) @@ -42,14 +48,17 @@ class Shelf(View): FakeShelf = namedtuple( "Shelf", ("identifier", "name", "user", "books", "privacy") ) - books = ( - models.Edition.viewer_aware_objects(request.user) - .filter( - # privacy is ensured because the shelves are already filtered above - shelfbook__shelf__in=shelves - ) - .distinct() - ) + if shelves_search_query: + logger.debug("AAAAAAAAAAAA") + all_books = models.Edition.viewer_aware_objects(request.user).filter( + # privacy is ensured because the shelves are already filtered above + shelfbook__shelf__in=shelves + ).distinct() + books = search(shelves_search_query, books=all_books) + else: + logger.debug("BBBBBBBBB") + books = shelf.books + shelf = FakeShelf("all", _("All books"), user, books, "public") if is_api_request(request) and shelf_identifier: @@ -103,6 +112,8 @@ class Shelf(View): "page_range": paginated.get_elided_page_range( page.number, on_each_side=2, on_ends=1 ), + "has_shelves_query": bool(shelves_search_query), + "shelves_search_query": shelves_search_query } return TemplateResponse(request, "shelf/shelf.html", data) diff --git a/docker-compose.yml b/docker-compose.yml index 4d4037681..bb0acbdd1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,8 @@ services: - pgdata:/var/lib/postgresql/data networks: - main + ports: + - "5432:5432" web: build: . env_file: .env