Hide deleted lists; add some api fields: volume, last change; other small api-related...
[wolnelektury.git] / src / catalogue / api / serializers.py
1 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
3 #
4 from rest_framework import serializers
5 from api.fields import AbsoluteURLField, LegacyMixin, ThumbnailField
6 from catalogue.models import Book, Collection, Tag, BookMedia, Fragment
7 from .fields import BookLiked, EmbargoURLField
8
9
10 class TagSerializer(serializers.ModelSerializer):
11     url = AbsoluteURLField()
12     href = AbsoluteURLField(
13         view_name='catalogue_api_tag',
14         view_args=('category', 'slug')
15     )
16
17     class Meta:
18         model = Tag
19         fields = ['url', 'href', 'name', 'slug']
20
21
22 class TagDetailSerializer(serializers.ModelSerializer):
23     url = AbsoluteURLField()
24
25     class Meta:
26         model = Tag
27         fields = [
28             'name', 'url', 'sort_key',
29             'description',
30             'description_pl',
31             'plural', 'genre_epoch_specific',
32             'adjective_feminine_singular', 'adjective_nonmasculine_plural',
33             'genitive', 'collective_noun',
34         ]
35         write_only_fields = [
36             'description_pl',
37             'plural', 'genre_epoch_specific',
38             'adjective_feminine_singular', 'adjective_nonmasculine_plural',
39             'genitive', 'collective_noun',
40         ]
41
42
43 class AuthorItemSerializer(serializers.ModelSerializer):
44     url = AbsoluteURLField()
45     href = AbsoluteURLField(
46         view_name='catalogue_api_author',
47         view_args=('slug',)
48     )
49
50     class Meta:
51         model = Tag
52         fields = [
53             'id', 'url', 'href', 'name', 'slug'
54         ]
55
56 class AuthorSerializer(AuthorItemSerializer):
57     photo_thumb = ThumbnailField('139x193', source='photo')
58
59     class Meta:
60         model = Tag
61         fields = [
62             'id', 'url', 'href', 'name', 'slug', 'sort_key', 'description',
63             'genitive', 'photo', 'photo_thumb', 'photo_attribution',
64         ]
65
66 class EpochItemSerializer(serializers.ModelSerializer):
67     url = AbsoluteURLField()
68     href = AbsoluteURLField(
69         view_name='catalogue_api_epoch',
70         view_args=('slug',)
71     )
72     class Meta:
73         model = Tag
74         fields = ['id', 'url', 'href', 'name', 'slug']
75
76 class EpochSerializer(EpochItemSerializer):
77     class Meta:
78         model = Tag
79         fields = [
80             'url', 'href', 'name', 'slug', 'sort_key', 'description',
81             'adjective_feminine_singular', 'adjective_nonmasculine_plural',
82         ]
83
84 class GenreItemSerializer(serializers.ModelSerializer):
85     url = AbsoluteURLField()
86     href = AbsoluteURLField(
87         view_name='catalogue_api_genre',
88         view_args=('slug',)
89     )
90     class Meta:
91         model = Tag
92         fields = ['id', 'url', 'href', 'name', 'slug']
93
94 class GenreSerializer(GenreItemSerializer):
95     class Meta:
96         model = Tag
97         fields = [
98             'url', 'href', 'name', 'slug', 'sort_key', 'description',
99             'plural', 'genre_epoch_specific',
100         ]
101
102 class KindItemSerializer(serializers.ModelSerializer):
103     url = AbsoluteURLField()
104     href = AbsoluteURLField(
105         view_name='catalogue_api_kind',
106         view_args=('slug',)
107     )
108     class Meta:
109         model = Tag
110         fields = ['id', 'url', 'href', 'name', 'slug']
111
112 class KindSerializer(KindItemSerializer):
113     class Meta:
114         model = Tag
115         fields = [
116             'url', 'href', 'name', 'slug', 'sort_key', 'description',
117             'collective_noun',
118         ]
119
120 class ThemeSerializer(serializers.ModelSerializer):
121     url = AbsoluteURLField()
122     href = AbsoluteURLField(
123         view_name='catalogue_api_theme',
124         view_args=('slug',)
125     )
126     class Meta:
127         model = Tag
128         fields = [
129             'url', 'href', 'name', 'slug', 'sort_key', 'description',
130         ]
131
132
133 class TranslatorSerializer(serializers.Serializer):
134     name = serializers.CharField(source='*')
135
136
137 class BookSerializer2(serializers.ModelSerializer):
138     url = AbsoluteURLField()
139     href = AbsoluteURLField(view_name='catalogue_api_book', view_args=['slug'])
140     xml = EmbargoURLField(source='xml_url')
141     html = EmbargoURLField(source='html_url')
142     txt = EmbargoURLField(source='txt_url')
143     fb2 = EmbargoURLField(source='fb2_url')
144     epub = EmbargoURLField(source='epub_url')
145     mobi = EmbargoURLField(source='mobi_url')
146     pdf = EmbargoURLField(source='pdf_url')
147
148     authors = AuthorItemSerializer(many=True)
149     translators = AuthorItemSerializer(many=True)
150     epochs = EpochItemSerializer(many=True)
151     genres = GenreItemSerializer(many=True)
152     kinds = KindItemSerializer(many=True)
153     parent = serializers.HyperlinkedRelatedField(
154         read_only=True,
155         view_name='catalogue_api_book',
156         lookup_field='slug'
157     )
158     children = serializers.SerializerMethodField()
159     audiences = serializers.ListField(source='audiences_pl')
160
161     class Meta:
162         model = Book
163         fields = [
164             'slug', 'title', 'full_sort_key',
165             'href', 'url', 'language',
166             'authors', 'translators',
167             'epochs', 'genres', 'kinds',
168             'children',
169             'parent', 'preview',
170             'epub', 'mobi', 'pdf', 'html', 'txt', 'fb2', 'xml',
171             'cover_thumb', 'cover',
172             'isbn_pdf', 'isbn_epub', 'isbn_mobi',
173             'abstract',
174             'has_mp3_file', 'has_sync_file',
175             'elevenreader_link', 'content_warnings', 'audiences',
176             'changed_at', 'read_time', 'pages', 'redakcja'
177         ]
178
179     def get_children(self, obj):
180         return list(obj.get_children().values('slug', 'title'))
181
182 class BookSerializer11Labs(serializers.ModelSerializer):
183     url = AbsoluteURLField()
184     href = AbsoluteURLField(view_name='catalogue_api_book', view_args=['slug'])
185     html = EmbargoURLField(source='html_nonotes_url')
186
187     authors = AuthorItemSerializer(many=True)
188     translators = AuthorItemSerializer(many=True)
189     epochs = EpochItemSerializer(many=True)
190     genres = GenreItemSerializer(many=True)
191     kinds = KindItemSerializer(many=True)
192     parent = serializers.HyperlinkedRelatedField(
193         read_only=True,
194         view_name='catalogue_api_book',
195         lookup_field='slug'
196     )
197
198     class Meta:
199         model = Book
200         fields = [
201             'slug', 'title', 'full_sort_key',
202             'href', 'url', 'language',
203             'authors', 'translators',
204             'epochs', 'genres', 'kinds',
205             #'children',
206             'parent', 'preview',
207             'html',
208             'cover_thumb', 'cover',
209             'isbn_pdf', 'isbn_epub', 'isbn_mobi',
210         ]
211
212
213 class BookSerializer(LegacyMixin, serializers.ModelSerializer):
214     author = serializers.CharField(source='author_unicode')
215     kind = serializers.CharField(source='kind_unicode')
216     epoch = serializers.CharField(source='epoch_unicode')
217     genre = serializers.CharField(source='genre_unicode')
218     liked = BookLiked()
219
220     simple_thumb = serializers.FileField(source='cover_api_thumb')
221     href = AbsoluteURLField(view_name='catalogue_api_book', view_args=['slug'])
222     url = AbsoluteURLField()
223     cover_thumb = ThumbnailField('139x193', source='cover')
224
225     class Meta:
226         model = Book
227         fields = [
228             'kind', 'full_sort_key', 'title', 'url', 'cover_color', 'author',
229             'cover', 'epoch', 'href', 'has_audio', 'genre',
230             'simple_thumb', 'slug', 'cover_thumb', 'liked']
231         legacy_non_null_fields = [
232             'kind', 'author', 'epoch', 'genre',
233             'cover', 'simple_thumb', 'cover_thumb']
234
235
236 class BookListSerializer(BookSerializer):
237     cover = serializers.CharField()
238     cover_thumb = serializers.CharField()
239
240     Meta = BookSerializer.Meta
241
242
243 class FilterBookListSerializer(BookListSerializer):
244     key = serializers.CharField()
245
246     class Meta:
247         model = Book
248         fields = BookListSerializer.Meta.fields + ['key']
249         legacy_non_null_fields = BookListSerializer.Meta.legacy_non_null_fields
250
251
252 class MediaSerializer(LegacyMixin, serializers.ModelSerializer):
253     url = EmbargoURLField(source='file_url')
254
255     class Meta:
256         model = BookMedia
257         fields = ['url', 'director', 'type', 'name', 'artist']
258         legacy_non_null_fields = ['director', 'artist']
259
260
261 class MediaSerializer2(MediaSerializer):
262     size = serializers.SerializerMethodField()
263
264     class Meta:
265         model = BookMedia
266         fields = ['url', 'director', 'type', 'name', 'part_name', 'artist', 'duration', 'size']
267
268     def get_size(self, obj):
269         return obj.file.size
270
271
272 class BookDetailSerializer(LegacyMixin, serializers.ModelSerializer):
273     url = AbsoluteURLField()
274
275     authors = TagSerializer(many=True)
276     translators = TranslatorSerializer(many=True)
277     epochs = TagSerializer(many=True)
278     genres = TagSerializer(many=True)
279     kinds = TagSerializer(many=True)
280
281     fragment_data = serializers.DictField()
282     parent = BookSerializer()
283     children = BookSerializer(many=True)
284
285     xml = EmbargoURLField(source='xml_url')
286     html = EmbargoURLField(source='html_url')
287     txt = EmbargoURLField(source='txt_url')
288     fb2 = EmbargoURLField(source='fb2_url')
289     epub = EmbargoURLField(source='epub_url')
290     mobi = EmbargoURLField(source='mobi_url')
291     pdf = EmbargoURLField(source='pdf_url')
292     media = MediaSerializer(many=True)
293     cover_thumb = ThumbnailField('139x193', source='cover')
294     simple_thumb = serializers.FileField(source='cover_api_thumb')
295
296     class Meta:
297         model = Book
298         fields = [
299             'title', 'url', 'language',
300             'epochs', 'genres', 'kinds', 'authors', 'translators',
301             'fragment_data', 'children', 'parent', 'preview',
302             'epub', 'mobi', 'pdf', 'html', 'txt', 'fb2', 'xml', 'media', 'audio_length',
303             'cover_color', 'simple_cover', 'cover_thumb', 'cover', 'simple_thumb',
304             'isbn_pdf', 'isbn_epub', 'isbn_mobi',
305         ]
306         legacy_non_null_fields = ['html', 'txt', 'fb2', 'epub', 'mobi', 'pdf',
307                                   'cover', 'simple_cover', 'cover_thumb', 'simple_thumb']
308
309
310 class BookPreviewSerializer(BookDetailSerializer):
311     class Meta:
312         model = Book
313         fields = BookDetailSerializer.Meta.fields + ['slug']
314         legacy_non_null_fields = BookDetailSerializer.Meta.legacy_non_null_fields
315
316
317 class EbookSerializer(BookListSerializer):
318     txt = EmbargoURLField(source='txt_url')
319     fb2 = EmbargoURLField(source='fb2_url')
320     epub = EmbargoURLField(source='epub_url')
321     mobi = EmbargoURLField(source='mobi_url')
322     pdf = EmbargoURLField(source='pdf_url')
323
324     class Meta:
325         model = Book
326         fields = ['author', 'href', 'title', 'cover', 'slug'] + Book.ebook_formats
327         legacy_non_null_fields = ['author', 'cover'] + Book.ebook_formats
328
329
330 class CollectionListSerializer(serializers.ModelSerializer):
331     url = AbsoluteURLField()
332     href = AbsoluteURLField(view_name='collection-detail', view_args=['slug'])
333
334     class Meta:
335         model = Collection
336         fields = ['url', 'href', 'title']
337
338
339 class CollectionSerializer(serializers.ModelSerializer):
340     books = BookSerializer(many=True, source='get_books', read_only=True)
341     authors = TagSerializer(many=True, read_only=True)
342     book_slugs = serializers.CharField(write_only=True, required=False)
343     author_slugs = serializers.CharField(write_only=True, required=False)
344     url = AbsoluteURLField()
345
346     class Meta:
347         model = Collection
348         fields = [
349             'url', 'books', 'description', 'title',
350             'book_slugs', 'authors', 'author_slugs'
351         ]
352
353     def update(self, instance, validated_data):
354         instance = super().update(instance, validated_data)
355         author_slugs = validated_data.get('author_slugs', '').strip().split()
356         if author_slugs:
357             authors = Tag.objects.filter(
358                 category='author',
359                 slug__in=author_slugs
360             )
361         else:
362             authors = []
363         instance.authors.set(authors)
364         return instance
365
366
367 class FragmentSerializer(serializers.ModelSerializer):
368     book = BookSerializer()
369     url = AbsoluteURLField()
370     href = AbsoluteURLField(source='get_api_url')
371
372     class Meta:
373         model = Fragment
374         fields = ['book', 'url', 'anchor', 'href']
375
376
377 class FragmentDetailSerializer(serializers.ModelSerializer):
378     book = BookSerializer()
379     url = AbsoluteURLField()
380     themes = TagSerializer(many=True)
381
382     class Meta:
383         model = Fragment
384         fields = ['book', 'anchor', 'text', 'url', 'themes']
385
386
387 class FragmentSerializer2(serializers.ModelSerializer):
388     url = AbsoluteURLField()
389     html = serializers.CharField(source='text')
390
391     class Meta:
392         model = Fragment
393         fields = ['anchor', 'html', 'url']
394
395
396 class FilterTagSerializer(serializers.ModelSerializer):
397     class Meta:
398         model = Tag
399         fields = ['id', 'category', 'name', 'slug']