2021-03-08 16:49:10 +00:00
|
|
|
""" the good stuff! the books! """
|
2021-01-13 17:54:35 +00:00
|
|
|
from django.core.paginator import Paginator
|
|
|
|
from django.contrib.auth.decorators import login_required, permission_required
|
|
|
|
from django.db import transaction
|
|
|
|
from django.db.models import Avg, Q
|
|
|
|
from django.http import HttpResponseNotFound
|
|
|
|
from django.shortcuts import get_object_or_404, redirect
|
|
|
|
from django.template.response import TemplateResponse
|
|
|
|
from django.utils.decorators import method_decorator
|
|
|
|
from django.views import View
|
|
|
|
from django.views.decorators.http import require_POST
|
|
|
|
|
|
|
|
from bookwyrm import forms, models
|
|
|
|
from bookwyrm.activitypub import ActivitypubResponse
|
|
|
|
from bookwyrm.connectors import connector_manager
|
|
|
|
from bookwyrm.settings import PAGE_LENGTH
|
|
|
|
from .helpers import is_api_request, get_activity_feed, get_edition
|
2021-02-15 19:30:22 +00:00
|
|
|
from .helpers import privacy_filter
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
# pylint: disable= no-self-use
|
|
|
|
class Book(View):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" a book! this is the stuff """
|
|
|
|
|
2021-01-13 17:54:35 +00:00
|
|
|
def get(self, request, book_id):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" info about a book """
|
2021-01-13 17:54:35 +00:00
|
|
|
try:
|
2021-03-08 16:49:10 +00:00
|
|
|
page = int(request.GET.get("page", 1))
|
2021-01-13 17:54:35 +00:00
|
|
|
except ValueError:
|
|
|
|
page = 1
|
|
|
|
|
|
|
|
try:
|
|
|
|
book = models.Book.objects.select_subclasses().get(id=book_id)
|
|
|
|
except models.Book.DoesNotExist:
|
|
|
|
return HttpResponseNotFound()
|
|
|
|
|
|
|
|
if is_api_request(request):
|
|
|
|
return ActivitypubResponse(book.to_activity())
|
|
|
|
|
|
|
|
if isinstance(book, models.Work):
|
|
|
|
book = book.get_default_edition()
|
|
|
|
if not book:
|
|
|
|
return HttpResponseNotFound()
|
|
|
|
|
|
|
|
work = book.parent_work
|
|
|
|
if not work:
|
|
|
|
return HttpResponseNotFound()
|
|
|
|
|
|
|
|
# all reviews for the book
|
2021-02-24 20:24:19 +00:00
|
|
|
reviews = models.Review.objects.filter(book__in=work.editions.all())
|
|
|
|
reviews = get_activity_feed(request.user, queryset=reviews)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
# the reviews to show
|
2021-03-08 16:49:10 +00:00
|
|
|
paginated = Paginator(
|
|
|
|
reviews.exclude(Q(content__isnull=True) | Q(content="")), PAGE_LENGTH
|
|
|
|
)
|
2021-01-13 17:54:35 +00:00
|
|
|
reviews_page = paginated.page(page)
|
|
|
|
|
|
|
|
user_tags = readthroughs = user_shelves = other_edition_shelves = []
|
|
|
|
if request.user.is_authenticated:
|
|
|
|
user_tags = models.UserTag.objects.filter(
|
|
|
|
book=book, user=request.user
|
2021-03-08 16:49:10 +00:00
|
|
|
).values_list("tag__identifier", flat=True)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
readthroughs = models.ReadThrough.objects.filter(
|
|
|
|
user=request.user,
|
|
|
|
book=book,
|
2021-03-08 16:49:10 +00:00
|
|
|
).order_by("start_date")
|
2021-01-13 17:54:35 +00:00
|
|
|
|
2021-01-17 20:59:53 +00:00
|
|
|
for readthrough in readthroughs:
|
2021-03-08 16:49:10 +00:00
|
|
|
readthrough.progress_updates = (
|
|
|
|
readthrough.progressupdate_set.all().order_by("-updated_date")
|
|
|
|
)
|
2021-01-17 20:59:53 +00:00
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
user_shelves = models.ShelfBook.objects.filter(user=request.user, book=book)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
other_edition_shelves = models.ShelfBook.objects.filter(
|
|
|
|
~Q(book=book),
|
2021-02-04 22:27:26 +00:00
|
|
|
user=request.user,
|
2021-01-13 17:54:35 +00:00
|
|
|
book__parent_work=book.parent_work,
|
|
|
|
)
|
|
|
|
|
|
|
|
data = {
|
2021-03-08 16:49:10 +00:00
|
|
|
"book": book,
|
|
|
|
"reviews": reviews_page,
|
|
|
|
"review_count": reviews.count(),
|
|
|
|
"ratings": reviews.filter(Q(content__isnull=True) | Q(content="")),
|
|
|
|
"rating": reviews.aggregate(Avg("rating"))["rating__avg"],
|
|
|
|
"tags": models.UserTag.objects.filter(book=book),
|
|
|
|
"lists": privacy_filter(
|
2021-03-07 16:37:39 +00:00
|
|
|
request.user, book.list_set.filter(listitem__approved=True)
|
2021-02-24 19:35:19 +00:00
|
|
|
),
|
2021-03-08 16:49:10 +00:00
|
|
|
"user_tags": user_tags,
|
|
|
|
"user_shelves": user_shelves,
|
|
|
|
"other_edition_shelves": other_edition_shelves,
|
|
|
|
"readthroughs": readthroughs,
|
|
|
|
"path": "/book/%s" % book_id,
|
2021-01-13 17:54:35 +00:00
|
|
|
}
|
2021-03-08 16:49:10 +00:00
|
|
|
return TemplateResponse(request, "book.html", data)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
@method_decorator(login_required, name="dispatch")
|
2021-01-13 17:54:35 +00:00
|
|
|
@method_decorator(
|
2021-03-08 16:49:10 +00:00
|
|
|
permission_required("bookwyrm.edit_book", raise_exception=True), name="dispatch"
|
|
|
|
)
|
2021-01-13 17:54:35 +00:00
|
|
|
class EditBook(View):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" edit a book """
|
|
|
|
|
2021-01-13 17:54:35 +00:00
|
|
|
def get(self, request, book_id):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" info about a book """
|
2021-01-13 17:54:35 +00:00
|
|
|
book = get_edition(book_id)
|
|
|
|
if not book.description:
|
|
|
|
book.description = book.parent_work.description
|
2021-03-08 16:49:10 +00:00
|
|
|
data = {"book": book, "form": forms.EditionForm(instance=book)}
|
|
|
|
return TemplateResponse(request, "edit_book.html", data)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
def post(self, request, book_id):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" edit a book cool """
|
2021-01-13 17:54:35 +00:00
|
|
|
book = get_object_or_404(models.Edition, id=book_id)
|
|
|
|
|
|
|
|
form = forms.EditionForm(request.POST, request.FILES, instance=book)
|
|
|
|
if not form.is_valid():
|
2021-03-08 16:49:10 +00:00
|
|
|
data = {"book": book, "form": form}
|
|
|
|
return TemplateResponse(request, "edit_book.html", data)
|
2021-01-13 17:54:35 +00:00
|
|
|
book = form.save()
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
return redirect("/book/%s" % book.id)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Editions(View):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" list of editions """
|
|
|
|
|
2021-01-13 17:54:35 +00:00
|
|
|
def get(self, request, book_id):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" list of editions of a book """
|
2021-01-13 17:54:35 +00:00
|
|
|
work = get_object_or_404(models.Work, id=book_id)
|
|
|
|
|
|
|
|
if is_api_request(request):
|
|
|
|
return ActivitypubResponse(work.to_edition_list(**request.GET))
|
|
|
|
|
|
|
|
data = {
|
2021-03-08 16:49:10 +00:00
|
|
|
"editions": work.editions.order_by("-edition_rank").all(),
|
|
|
|
"work": work,
|
2021-01-13 17:54:35 +00:00
|
|
|
}
|
2021-03-08 16:49:10 +00:00
|
|
|
return TemplateResponse(request, "editions.html", data)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_POST
|
|
|
|
def upload_cover(request, book_id):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" upload a new cover """
|
2021-01-13 17:54:35 +00:00
|
|
|
book = get_object_or_404(models.Edition, id=book_id)
|
|
|
|
|
|
|
|
form = forms.CoverForm(request.POST, request.FILES, instance=book)
|
|
|
|
if not form.is_valid():
|
2021-03-08 16:49:10 +00:00
|
|
|
return redirect("/book/%d" % book.id)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
2021-02-28 21:40:57 +00:00
|
|
|
book.last_edited_by = request.user
|
2021-03-08 16:49:10 +00:00
|
|
|
book.cover = form.files["cover"]
|
2021-01-13 17:54:35 +00:00
|
|
|
book.save()
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
return redirect("/book/%s" % book.id)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_POST
|
2021-03-08 16:49:10 +00:00
|
|
|
@permission_required("bookwyrm.edit_book", raise_exception=True)
|
2021-01-13 17:54:35 +00:00
|
|
|
def add_description(request, book_id):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" upload a new cover """
|
|
|
|
if not request.method == "POST":
|
|
|
|
return redirect("/")
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
book = get_object_or_404(models.Edition, id=book_id)
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
description = request.POST.get("description")
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
book.description = description
|
2021-02-28 21:40:57 +00:00
|
|
|
book.last_edited_by = request.user
|
2021-01-13 17:54:35 +00:00
|
|
|
book.save()
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
return redirect("/book/%s" % book.id)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
@require_POST
|
|
|
|
def resolve_book(request):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" figure out the local path to a book from a remote_id """
|
|
|
|
remote_id = request.POST.get("remote_id")
|
2021-01-13 17:54:35 +00:00
|
|
|
connector = connector_manager.get_or_create_connector(remote_id)
|
|
|
|
book = connector.get_or_create_book(remote_id)
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
return redirect("/book/%d" % book.id)
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
@require_POST
|
|
|
|
@transaction.atomic
|
|
|
|
def switch_edition(request):
|
2021-03-08 16:49:10 +00:00
|
|
|
""" switch your copy of a book to a different edition """
|
|
|
|
edition_id = request.POST.get("edition")
|
2021-01-13 17:54:35 +00:00
|
|
|
new_edition = get_object_or_404(models.Edition, id=edition_id)
|
|
|
|
shelfbooks = models.ShelfBook.objects.filter(
|
2021-03-08 16:49:10 +00:00
|
|
|
book__parent_work=new_edition.parent_work, shelf__user=request.user
|
2021-01-13 17:54:35 +00:00
|
|
|
)
|
|
|
|
for shelfbook in shelfbooks.all():
|
2021-02-09 20:07:45 +00:00
|
|
|
with transaction.atomic():
|
|
|
|
models.ShelfBook.objects.create(
|
|
|
|
created_date=shelfbook.created_date,
|
|
|
|
user=shelfbook.user,
|
|
|
|
shelf=shelfbook.shelf,
|
2021-03-08 16:49:10 +00:00
|
|
|
book=new_edition,
|
2021-02-09 20:07:45 +00:00
|
|
|
)
|
|
|
|
shelfbook.delete()
|
2021-01-13 17:54:35 +00:00
|
|
|
|
|
|
|
readthroughs = models.ReadThrough.objects.filter(
|
2021-03-08 16:49:10 +00:00
|
|
|
book__parent_work=new_edition.parent_work, user=request.user
|
2021-01-13 17:54:35 +00:00
|
|
|
)
|
|
|
|
for readthrough in readthroughs.all():
|
|
|
|
readthrough.book = new_edition
|
|
|
|
readthrough.save()
|
|
|
|
|
2021-03-08 16:49:10 +00:00
|
|
|
return redirect("/book/%d" % new_edition.id)
|