""" book list views""" from django.core.paginator import Paginator from django.db.models import Avg, DecimalField from django.db.models.functions import Coalesce from django.http import Http404 from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse from django.views import View from django.views.decorators.clickjacking import xframe_options_exempt from bookwyrm import models from bookwyrm.settings import PAGE_LENGTH # pylint: disable=no-self-use class EmbedList(View): """embeded book list page""" def get(self, request, list_id, list_key): """display a book list""" book_list = get_object_or_404(models.List, id=list_id) embed_key = str(book_list.embed_key.hex) if list_key != embed_key: raise Http404() # sort_by shall be "order" unless a valid alternative is given sort_by = request.GET.get("sort_by", "order") if sort_by not in ("order", "title", "rating"): sort_by = "order" # direction shall be "ascending" unless a valid alternative is given direction = request.GET.get("direction", "ascending") if direction not in ("ascending", "descending"): direction = "ascending" directional_sort_by = { "order": "order", "title": "book__title", "rating": "average_rating", }[sort_by] if direction == "descending": directional_sort_by = "-" + directional_sort_by items = book_list.listitem_set.prefetch_related("user", "book", "book__authors") if sort_by == "rating": items = items.annotate( average_rating=Avg( Coalesce("book__review__rating", 0.0), output_field=DecimalField(), ) ) items = items.filter(approved=True).order_by(directional_sort_by) paginated = Paginator(items, PAGE_LENGTH) page = paginated.get_page(request.GET.get("page")) data = { "list": book_list, "items": page, "page_range": paginated.get_elided_page_range( page.number, on_each_side=2, on_ends=1 ), } return TemplateResponse(request, "lists/embed-list.html", data) @xframe_options_exempt def unsafe_embed_list(request, *args, **kwargs): """allows the EmbedList view to be loaded through unsafe iframe origins""" embed_list_view = EmbedList.as_view() return embed_list_view(request, *args, **kwargs)