From 27540194355a3118d8330262b6312b3f280f7b9a Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Wed, 26 Feb 2025 16:12:02 +0100 Subject: [PATCH] api for partner --- requirements/requirements.txt | 2 +- src/catalogue/api/serializers.py | 31 +++++++++++++++++++ src/catalogue/api/urls2.py | 4 +++ src/catalogue/api/views.py | 12 +++++++ src/catalogue/fields.py | 20 ++++++++++++ ...le_book_html_nonotes_file_etag_and_more.py | 30 ++++++++++++++++++ src/catalogue/models/book.py | 9 +++++- 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py diff --git a/requirements/requirements.txt b/requirements/requirements.txt index c3934fea4..898a609ae 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -39,7 +39,7 @@ mutagen==1.47 sorl-thumbnail==12.10.0 # home-brewed & dependencies -librarian==24.5.6 +librarian==24.5.7 # celery tasks celery[redis]==5.4.0 diff --git a/src/catalogue/api/serializers.py b/src/catalogue/api/serializers.py index 5f96e0270..3e3874d3f 100644 --- a/src/catalogue/api/serializers.py +++ b/src/catalogue/api/serializers.py @@ -158,6 +158,37 @@ class BookSerializer2(serializers.ModelSerializer): 'isbn_pdf', 'isbn_epub', 'isbn_mobi', ] +class BookSerializer11Labs(serializers.ModelSerializer): + url = AbsoluteURLField() + href = AbsoluteURLField(view_name='catalogue_api_book', view_args=['slug']) + html = EmbargoURLField(source='html_nonotes_url') + + authors = AuthorItemSerializer(many=True) + translators = AuthorItemSerializer(many=True) + epochs = EpochItemSerializer(many=True) + genres = GenreItemSerializer(many=True) + kinds = KindItemSerializer(many=True) + parent = serializers.HyperlinkedRelatedField( + read_only=True, + view_name='catalogue_api_book', + lookup_field='slug' + ) + + class Meta: + model = Book + fields = [ + 'slug', 'title', 'full_sort_key', + 'href', 'url', 'language', + 'authors', 'translators', + 'epochs', 'genres', 'kinds', + #'children', + 'parent', 'preview', + 'html', + 'cover_thumb', 'cover', + 'isbn_pdf', 'isbn_epub', 'isbn_mobi', + ] + + class BookSerializer(LegacyMixin, serializers.ModelSerializer): author = serializers.CharField(source='author_unicode') kind = serializers.CharField(source='kind_unicode') diff --git a/src/catalogue/api/urls2.py b/src/catalogue/api/urls2.py index 8748e2cf1..164cdca39 100644 --- a/src/catalogue/api/urls2.py +++ b/src/catalogue/api/urls2.py @@ -11,6 +11,10 @@ urlpatterns = [ piwik_track_view(views.BookList2.as_view()), name='catalogue_api_book_list' ), + path('11labs/books/', + piwik_track_view(views.BookList11Labs.as_view()), + name='catalogue_api_book_list' + ), path('books//', piwik_track_view(views.BookDetail2.as_view()), name='catalogue_api_book' diff --git a/src/catalogue/api/views.py b/src/catalogue/api/views.py index 9c8f4f177..b55b21451 100644 --- a/src/catalogue/api/views.py +++ b/src/catalogue/api/views.py @@ -196,6 +196,18 @@ class BookList2(ListAPIView): return books +class BookList11Labs(BookList2): + serializer_class = serializers.BookSerializer11Labs + + def get_queryset(self): + books = Book.objects.all() + books = books.filter(findable=True) + books = books.filter(license='') + books = order_books(books, True) + + return books + + @vary_on_auth # Because of 'liked'. class BookDetail(RetrieveAPIView): queryset = Book.objects.all() diff --git a/src/catalogue/fields.py b/src/catalogue/fields.py index 9c5696fa6..2d35357eb 100644 --- a/src/catalogue/fields.py +++ b/src/catalogue/fields.py @@ -398,6 +398,26 @@ class HtmlField(EbookField): return wldoc.as_html(gallery_path=gal_path, gallery_url=gal_url, base_url=absolute_url(gal_url)) +class HtmlNonotesField(EbookField): + ext = 'html' + for_parents = False + directory = 'html_nonotes' + + @staticmethod + def transform(wldoc, book): + # ugly, but we can't use wldoc.book_info here + from librarian import DCNS + url_elem = wldoc.edoc.getroot().find('.//' + DCNS('identifier.url')) + if url_elem is None: + gal_url = '' + gal_path = '' + else: + slug = url_elem.text.rstrip('/').rsplit('/', 1)[1] + gal_url = gallery_url(slug=slug) + gal_path = gallery_path(slug=slug) + return wldoc.as_html(gallery_path=gal_path, gallery_url=gal_url, base_url=absolute_url(gal_url), flags=['nonotes']) + + class CoverField(EbookField): ext = 'jpg' directory = 'cover' diff --git a/src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py b/src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py new file mode 100644 index 000000000..bd297d4c6 --- /dev/null +++ b/src/catalogue/migrations/0049_book_html_nonotes_file_book_html_nonotes_file_etag_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.0.8 on 2025-02-26 14:46 + +import catalogue.fields +from django.db import migrations, models +import fnpdjango.storage + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0048_remove_collection_kind_remove_tag_for_books_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='book', + name='html_nonotes_file', + field=catalogue.fields.HtmlNonotesField(etag_field_name='html_nonotes_file_etag', storage=fnpdjango.storage.BofhFileSystemStorage()), + ), + migrations.AddField( + model_name='book', + name='html_nonotes_file_etag', + field=models.CharField(db_index=True, default='', editable=False, max_length=255), + ), + migrations.AddField( + model_name='book', + name='license', + field=models.CharField(blank=True, db_index=True, max_length=255, verbose_name='licencja'), + ), + ] diff --git a/src/catalogue/models/book.py b/src/catalogue/models/book.py index 29e375464..4080cc269 100644 --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@ -43,6 +43,7 @@ class Book(models.Model): common_slug = models.SlugField('wspólny slug', max_length=120, db_index=True) language = models.CharField('kod języka', max_length=3, db_index=True, default=app_settings.DEFAULT_LANGUAGE) description = models.TextField('opis', blank=True) + license = models.CharField('licencja', max_length=255, blank=True, db_index=True) abstract = models.TextField('abstrakt', blank=True) toc = models.TextField('spis treści', blank=True) created_at = models.DateTimeField('data utworzenia', auto_now_add=True, db_index=True) @@ -62,6 +63,7 @@ class Book(models.Model): # files generated during publication xml_file = fields.XmlField(storage=bofh_storage, with_etag=False) html_file = fields.HtmlField(storage=bofh_storage) + html_nonotes_file = fields.HtmlNonotesField(storage=bofh_storage) fb2_file = fields.Fb2Field(storage=bofh_storage) txt_file = fields.TxtField(storage=bofh_storage) epub_file = fields.EpubField(storage=bofh_storage) @@ -79,7 +81,7 @@ class Book(models.Model): 'okładka dla Ebookpoint') ebook_formats = constants.EBOOK_FORMATS - formats = ebook_formats + ['html', 'xml'] + formats = ebook_formats + ['html', 'xml', 'html_nonotes'] parent = models.ForeignKey('self', models.CASCADE, blank=True, null=True, related_name='children') ancestor = models.ManyToManyField('self', blank=True, editable=False, related_name='descendant', symmetrical=False) @@ -375,6 +377,9 @@ class Book(models.Model): def html_url(self): return self.media_url('html') + def html_nonotes_url(self): + return self.media_url('html_nonotes') + def pdf_url(self): return self.media_url('pdf') @@ -635,6 +640,7 @@ class Book(models.Model): book.findable = findable book.language = book_info.language book.title = book_info.title + book.license = book_info.license if book_info.variant_of: book.common_slug = book_info.variant_of.slug else: @@ -704,6 +710,7 @@ class Book(models.Model): for format_ in constants.EBOOK_FORMATS_WITH_CHILDREN: if format_ not in dont_build: getattr(book, '%s_file' % format_).build_delay() + book.html_nonotes_file.build_delay() if not settings.NO_SEARCH_INDEX and search_index and findable: tasks.index_book.delay(book.id) -- 2.20.1