2
0
Fork 0

Merge pull request #2616 from MeecoLabs/book-series-v1

Book Series v1: a very simple version to link to book series by name\

Resolves #644
This commit is contained in:
Hugh Rundle 2023-02-08 21:14:51 +11:00 committed by GitHub
commit e88f1f0b8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 117 additions and 1 deletions

View file

@ -46,7 +46,7 @@
<meta itemprop="isPartOf" content="{{ book.series | escape }}">
<meta itemprop="volumeNumber" content="{{ book.series_number }}">
({{ book.series }}{% if book.series_number %} #{{ book.series_number }}{% endif %})
(<a href="{% url 'book-series-by' book.authors.first.id %}?series_name={{ book.series }}">{{ book.series }}{% if book.series_number %} #{{ book.series_number }}{% endif %}</a>)
{% endif %}
</p>
{% endif %}

View file

@ -0,0 +1,35 @@
{% extends 'layout.html' %}
{% load i18n %}
{% load book_display_tags %}
{% block title %}{{ series_name }}{% endblock %}
{% block content %}
<div class="block">
<h1 class="title">{{ series_name }}</h1>
<div class="subtitle" dir="auto">
{% trans "Series by" %} <a
href="{{ author.local_path }}"
class="author {{ link_class }}"
itemprop="author"
itemscope
itemtype="https://schema.org/Thing"
><span
itemprop="name"
>{{ author.name }}</span></a>
</div>
<div class="columns is-multiline is-mobile">
{% for book in books %}
{% with book=book %}
<div class="column is-one-fifth-tablet is-half-mobile is-flex is-flex-direction-column">
<div class="is-flex-grow-1 mb-3">
<span class="subtitle">{% if book.series_number %}{% blocktrans with series_number=book.series_number %}Book {{ series_number }}{% endblocktrans %}{% else %}{% trans 'Unsorted Book' %}{% endif %}</span>
{% include 'landing/small-book.html' with book=book %}
</div>
</div>
{% endwith %}
{% endfor %}
</div>
</div>
{% endblock %}

View file

@ -638,6 +638,11 @@ urlpatterns = [
# books
re_path(rf"{BOOK_PATH}(.json)?/?$", views.Book.as_view(), name="book"),
re_path(rf"{BOOK_PATH}{regex.SLUG}/?$", views.Book.as_view(), name="book"),
re_path(
r"^series/by/(?P<author_id>\d+)/?$",
views.BookSeriesBy.as_view(),
name="book-series-by",
),
re_path(
rf"{BOOK_PATH}/(?P<user_statuses>review|comment|quote)/?$",
views.Book.as_view(),

View file

@ -55,6 +55,7 @@ from .books.books import (
add_description,
resolve_book,
)
from .books.series import BookSeriesBy
from .books.books import update_book_from_remote
from .books.edit_book import (
EditBook,

View file

@ -0,0 +1,75 @@
""" books belonging to the same series """
from sys import float_info
from django.views import View
from django.shortcuts import get_object_or_404
from django.template.response import TemplateResponse
from bookwyrm.views.helpers import is_api_request
from bookwyrm import models
def sort_by_series(book):
"""sort books using their series number"""
try:
return float(book.series_number)
except ValueError:
return float_info.max
# pylint: disable=no-self-use
class BookSeriesBy(View):
"""book series by author"""
def get(self, request, author_id):
"""lists all books in a series"""
series_name = request.GET.get("series_name")
if is_api_request(request):
pass
author = get_object_or_404(models.Author, id=author_id)
results = models.Edition.objects.filter(authors=author, series=series_name)
# when there are multiple editions of the same work
# pick the one with a series number or closest
work_ids = results.values_list("parent_work__id", flat=True).distinct()
# filter out multiple editions of the same work
numbered_books = []
dated_books = []
unsortable_books = []
for work_id in set(work_ids):
result = (
results.filter(parent_work=work_id)
.order_by("series_number", "-edition_rank")
.first()
)
if result.series_number:
numbered_books.append(result)
elif result.first_published_date or result.published_date:
dated_books.append(result)
else:
unsortable_books.append(result)
list_results = (
sorted(numbered_books, key=sort_by_series)
+ sorted(
dated_books,
key=lambda book: book.first_published_date
if book.first_published_date
else book.published_date,
)
+ sorted(
unsortable_books,
key=lambda book: book.sort_title if book.sort_title else book.title,
)
)
data = {
"series_name": series_name,
"author": author,
"books": list_results,
}
return TemplateResponse(request, "book/series.html", data)