Merge branch 'main' into add-feed-filters
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
""" the good stuff! the books! """
|
||||
from re import sub
|
||||
from dateutil.parser import parse as dateparse
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.contrib.postgres.search import SearchRank, SearchVector
|
||||
@ -11,10 +12,16 @@ from django.utils.decorators import method_decorator
|
||||
from django.views import View
|
||||
|
||||
from bookwyrm import book_search, forms, models
|
||||
|
||||
# from bookwyrm.activitypub.base_activity import ActivityObject
|
||||
from bookwyrm.utils.isni import (
|
||||
find_authors_by_name,
|
||||
build_author_from_isni,
|
||||
augment_author_metadata,
|
||||
)
|
||||
from bookwyrm.views.helpers import get_edition
|
||||
from .books import set_cover_from_url
|
||||
|
||||
|
||||
# pylint: disable=no-self-use
|
||||
@method_decorator(login_required, name="dispatch")
|
||||
@method_decorator(
|
||||
@ -33,6 +40,7 @@ class EditBook(View):
|
||||
data = {"book": book, "form": forms.EditionForm(instance=book)}
|
||||
return TemplateResponse(request, "book/edit/edit_book.html", data)
|
||||
|
||||
# pylint: disable=too-many-locals
|
||||
def post(self, request, book_id=None):
|
||||
"""edit a book cool"""
|
||||
# returns None if no match is found
|
||||
@ -43,12 +51,14 @@ class EditBook(View):
|
||||
if not form.is_valid():
|
||||
return TemplateResponse(request, "book/edit/edit_book.html", data)
|
||||
|
||||
add_author = request.POST.get("add_author")
|
||||
# we're adding an author through a free text field
|
||||
# filter out empty author fields
|
||||
add_author = [author for author in request.POST.getlist("add_author") if author]
|
||||
if add_author:
|
||||
data["add_author"] = add_author
|
||||
data["author_matches"] = []
|
||||
for author in add_author.split(","):
|
||||
data["isni_matches"] = []
|
||||
|
||||
for author in add_author:
|
||||
if not author:
|
||||
continue
|
||||
# check for existing authors
|
||||
@ -56,15 +66,35 @@ class EditBook(View):
|
||||
"aliases", weight="B"
|
||||
)
|
||||
|
||||
author_matches = (
|
||||
models.Author.objects.annotate(search=vector)
|
||||
.annotate(rank=SearchRank(vector, author))
|
||||
.filter(rank__gt=0.4)
|
||||
.order_by("-rank")[:5]
|
||||
)
|
||||
|
||||
isni_authors = find_authors_by_name(
|
||||
author, description=True
|
||||
) # find matches from ISNI API
|
||||
|
||||
# dedupe isni authors we already have in the DB
|
||||
exists = [
|
||||
i
|
||||
for i in isni_authors
|
||||
for a in author_matches
|
||||
if sub(r"\D", "", str(i.isni)) == sub(r"\D", "", str(a.isni))
|
||||
]
|
||||
|
||||
# pylint: disable=cell-var-from-loop
|
||||
matches = list(filter(lambda x: x not in exists, isni_authors))
|
||||
# combine existing and isni authors
|
||||
matches.extend(author_matches)
|
||||
|
||||
data["author_matches"].append(
|
||||
{
|
||||
"name": author.strip(),
|
||||
"matches": (
|
||||
models.Author.objects.annotate(search=vector)
|
||||
.annotate(rank=SearchRank(vector, author))
|
||||
.filter(rank__gt=0.4)
|
||||
.order_by("-rank")[:5]
|
||||
),
|
||||
"matches": matches,
|
||||
"existing_isnis": exists,
|
||||
}
|
||||
)
|
||||
|
||||
@ -122,6 +152,8 @@ class EditBook(View):
|
||||
class ConfirmEditBook(View):
|
||||
"""confirm edits to a book"""
|
||||
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-branches
|
||||
def post(self, request, book_id=None):
|
||||
"""edit a book cool"""
|
||||
# returns None if no match is found
|
||||
@ -147,9 +179,25 @@ class ConfirmEditBook(View):
|
||||
author = get_object_or_404(
|
||||
models.Author, id=request.POST[f"author_match-{i}"]
|
||||
)
|
||||
# update author metadata if the ISNI record is more complete
|
||||
isni = request.POST.get(f"isni-for-{match}", None)
|
||||
if isni is not None:
|
||||
augment_author_metadata(author, isni)
|
||||
except ValueError:
|
||||
# otherwise it's a name
|
||||
author = models.Author.objects.create(name=match)
|
||||
# otherwise it's a new author
|
||||
isni_match = request.POST.get(f"author_match-{i}")
|
||||
author_object = build_author_from_isni(isni_match)
|
||||
# with author data class from isni id
|
||||
if "author" in author_object:
|
||||
skeleton = models.Author.objects.create(
|
||||
name=author_object["author"].name
|
||||
)
|
||||
author = author_object["author"].to_model(
|
||||
model=models.Author, overwrite=True, instance=skeleton
|
||||
)
|
||||
else:
|
||||
# or it's just a name
|
||||
author = models.Author.objects.create(name=match)
|
||||
book.authors.add(author)
|
||||
|
||||
# create work, if needed
|
||||
|
@ -9,6 +9,7 @@ from django.views import View
|
||||
from django.views.decorators.http import require_POST
|
||||
|
||||
from bookwyrm import models
|
||||
from bookwyrm.views.shelf.shelf_actions import unshelve
|
||||
from .status import CreateStatus
|
||||
from .helpers import get_edition, handle_reading_status, is_api_request
|
||||
from .helpers import load_date_in_user_tz_as_utc
|
||||
@ -16,6 +17,7 @@ from .helpers import load_date_in_user_tz_as_utc
|
||||
|
||||
@method_decorator(login_required, name="dispatch")
|
||||
# pylint: disable=no-self-use
|
||||
# pylint: disable=too-many-return-statements
|
||||
class ReadingStatus(View):
|
||||
"""consider reading a book"""
|
||||
|
||||
@ -89,8 +91,21 @@ class ReadingStatus(View):
|
||||
privacy = request.POST.get("privacy")
|
||||
handle_reading_status(request.user, desired_shelf, book, privacy)
|
||||
|
||||
# if the request includes a "shelf" value we are using the 'move' button
|
||||
if bool(request.POST.get("shelf")):
|
||||
# unshelve the existing shelf
|
||||
this_shelf = request.POST.get("shelf")
|
||||
if (
|
||||
bool(current_status_shelfbook)
|
||||
and int(this_shelf) != int(current_status_shelfbook.shelf.id)
|
||||
and current_status_shelfbook.shelf.identifier
|
||||
!= desired_shelf.identifier
|
||||
):
|
||||
return unshelve(request, book_id=book_id)
|
||||
|
||||
if is_api_request(request):
|
||||
return HttpResponse()
|
||||
|
||||
return redirect(referer)
|
||||
|
||||
|
||||
|
@ -91,13 +91,13 @@ def shelve(request):
|
||||
|
||||
@login_required
|
||||
@require_POST
|
||||
def unshelve(request):
|
||||
def unshelve(request, book_id=False):
|
||||
"""remove a book from a user's shelf"""
|
||||
book = get_object_or_404(models.Edition, id=request.POST.get("book"))
|
||||
identity = book_id if book_id else request.POST.get("book")
|
||||
book = get_object_or_404(models.Edition, id=identity)
|
||||
shelf_book = get_object_or_404(
|
||||
models.ShelfBook, book=book, shelf__id=request.POST["shelf"]
|
||||
)
|
||||
shelf_book.raise_not_deletable(request.user)
|
||||
|
||||
shelf_book.delete()
|
||||
return redirect(request.headers.get("Referer", "/"))
|
||||
|
@ -54,6 +54,7 @@ class CreateStatus(View):
|
||||
data = {"book": book}
|
||||
return TemplateResponse(request, "compose.html", data)
|
||||
|
||||
# pylint: disable=too-many-branches
|
||||
def post(self, request, status_type, existing_status_id=None):
|
||||
"""create status of whatever type"""
|
||||
created = not existing_status_id
|
||||
@ -117,11 +118,12 @@ class CreateStatus(View):
|
||||
|
||||
status.save(created=created)
|
||||
|
||||
# update a readthorugh, if needed
|
||||
try:
|
||||
edit_readthrough(request)
|
||||
except Http404:
|
||||
pass
|
||||
# update a readthrough, if needed
|
||||
if bool(request.POST.get("id")):
|
||||
try:
|
||||
edit_readthrough(request)
|
||||
except Http404:
|
||||
pass
|
||||
|
||||
if is_api_request(request):
|
||||
return HttpResponse()
|
||||
|
Reference in New Issue
Block a user