mirror of
https://github.com/bookwyrm-social/bookwyrm.git
synced 2024-11-26 11:31:08 +00:00
Checkpoint
This commit is contained in:
parent
90cc28986e
commit
d93da4e86d
8 changed files with 66 additions and 21 deletions
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
25
bookwyrm/templates/shelf/search_my_books_form.html
Normal file
25
bookwyrm/templates/shelf/search_my_books_form.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
{% load i18n %}
|
||||
{% load utilities %}
|
||||
|
||||
<form class="navbar-item column is-align-items-start pt-5" action="{% url 'user-shelves' user|username %}">
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
{% trans "Search for a book" as my_shelves_search_placeholder %}
|
||||
<input aria-label="{{ my_shelves_search_placeholder }}" id="my-books-search" class="input" type="text" name="shelves_q" placeholder="{{ my_shelves_search_placeholder }}" value="{{ my_shelves_query }}" spellcheck="false">
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button" type="submit">
|
||||
<span class="icon icon-search" title="{% trans 'Search' %}">
|
||||
<span class="is-sr-only">{% trans "Search" %}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<button class="button" type="button" data-modal-open="barcode-scanner-modal">
|
||||
<span class="icon icon-barcode" title="{% trans 'Scan Barcode' %}" id="tour-barcode">
|
||||
<span class="is-sr-only">{% trans "Scan Barcode" %}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
|
@ -123,6 +123,7 @@
|
|||
</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% include 'shelf/search_my_books_form.html' with user=user query=query %}
|
||||
</h2>
|
||||
</div>
|
||||
{% if is_self and shelf.id %}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
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()
|
||||
)
|
||||
).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)
|
||||
|
|
|
@ -21,6 +21,8 @@ services:
|
|||
- pgdata:/var/lib/postgresql/data
|
||||
networks:
|
||||
- main
|
||||
ports:
|
||||
- "5432:5432"
|
||||
web:
|
||||
build: .
|
||||
env_file: .env
|
||||
|
|
Loading…
Reference in a new issue