Add missing constraint.
[wolnelektury.git] / src / catalogue / api / serializers.py
1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. 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 TranslatorSerializer(serializers.Serializer):
44     name = serializers.CharField(source='*')
45
46
47 class BookSerializer(LegacyMixin, serializers.ModelSerializer):
48     author = serializers.CharField(source='author_unicode')
49     kind = serializers.CharField(source='kind_unicode')
50     epoch = serializers.CharField(source='epoch_unicode')
51     genre = serializers.CharField(source='genre_unicode')
52     liked = BookLiked()
53
54     simple_thumb = serializers.FileField(source='cover_api_thumb')
55     href = AbsoluteURLField(view_name='catalogue_api_book', view_args=['slug'])
56     url = AbsoluteURLField()
57     cover_thumb = ThumbnailField('139x193', source='cover')
58
59     class Meta:
60         model = Book
61         fields = [
62             'kind', 'full_sort_key', 'title', 'url', 'cover_color', 'author',
63             'cover', 'epoch', 'href', 'has_audio', 'genre',
64             'simple_thumb', 'slug', 'cover_thumb', 'liked']
65         legacy_non_null_fields = [
66             'kind', 'author', 'epoch', 'genre',
67             'cover', 'simple_thumb', 'cover_thumb']
68
69
70 class BookListSerializer(BookSerializer):
71     cover = serializers.CharField()
72     cover_thumb = serializers.CharField()
73
74     Meta = BookSerializer.Meta
75
76
77 class FilterBookListSerializer(BookListSerializer):
78     key = serializers.CharField()
79
80     class Meta:
81         model = Book
82         fields = BookListSerializer.Meta.fields + ['key']
83         legacy_non_null_fields = BookListSerializer.Meta.legacy_non_null_fields
84
85
86 class MediaSerializer(LegacyMixin, serializers.ModelSerializer):
87     url = EmbargoURLField(source='file_url')
88
89     class Meta:
90         model = BookMedia
91         fields = ['url', 'director', 'type', 'name', 'artist']
92         legacy_non_null_fields = ['director', 'artist']
93
94
95 class BookDetailSerializer(LegacyMixin, serializers.ModelSerializer):
96     url = AbsoluteURLField()
97
98     authors = TagSerializer(many=True)
99     translators = TranslatorSerializer(many=True)
100     epochs = TagSerializer(many=True)
101     genres = TagSerializer(many=True)
102     kinds = TagSerializer(many=True)
103
104     fragment_data = serializers.DictField()
105     parent = BookSerializer()
106     children = BookSerializer(many=True)
107
108     xml = EmbargoURLField(source='xml_url')
109     html = EmbargoURLField(source='html_url')
110     txt = EmbargoURLField(source='txt_url')
111     fb2 = EmbargoURLField(source='fb2_url')
112     epub = EmbargoURLField(source='epub_url')
113     mobi = EmbargoURLField(source='mobi_url')
114     pdf = EmbargoURLField(source='pdf_url')
115     media = MediaSerializer(many=True)
116     cover_thumb = ThumbnailField('139x193', source='cover')
117     simple_thumb = serializers.FileField(source='cover_api_thumb')
118
119     class Meta:
120         model = Book
121         fields = [
122             'title', 'url', 'language',
123             'epochs', 'genres', 'kinds', 'authors', 'translators',
124             'fragment_data', 'children', 'parent', 'preview',
125             'epub', 'mobi', 'pdf', 'html', 'txt', 'fb2', 'xml', 'media', 'audio_length',
126             'cover_color', 'simple_cover', 'cover_thumb', 'cover', 'simple_thumb',
127             'isbn_pdf', 'isbn_epub', 'isbn_mobi',
128         ]
129         legacy_non_null_fields = ['html', 'txt', 'fb2', 'epub', 'mobi', 'pdf',
130                                   'cover', 'simple_cover', 'cover_thumb', 'simple_thumb']
131
132
133 class BookPreviewSerializer(BookDetailSerializer):
134     class Meta:
135         model = Book
136         fields = BookDetailSerializer.Meta.fields + ['slug']
137         legacy_non_null_fields = BookDetailSerializer.Meta.legacy_non_null_fields
138
139
140 class EbookSerializer(BookListSerializer):
141     txt = EmbargoURLField(source='txt_url')
142     fb2 = EmbargoURLField(source='fb2_url')
143     epub = EmbargoURLField(source='epub_url')
144     mobi = EmbargoURLField(source='mobi_url')
145     pdf = EmbargoURLField(source='pdf_url')
146
147     class Meta:
148         model = Book
149         fields = ['author', 'href', 'title', 'cover', 'slug'] + Book.ebook_formats
150         legacy_non_null_fields = ['author', 'cover'] + Book.ebook_formats
151
152
153 class CollectionListSerializer(serializers.ModelSerializer):
154     url = AbsoluteURLField()
155     href = AbsoluteURLField(view_name='collection-detail', view_args=['slug'])
156
157     class Meta:
158         model = Collection
159         fields = ['url', 'href', 'title']
160
161
162 class CollectionSerializer(serializers.ModelSerializer):
163     books = BookSerializer(many=True, source='get_books', read_only=True)
164     authors = TagSerializer(many=True, read_only=True)
165     book_slugs = serializers.CharField(write_only=True, required=False)
166     author_slugs = serializers.CharField(write_only=True, required=False)
167     url = AbsoluteURLField()
168
169     class Meta:
170         model = Collection
171         fields = [
172             'url', 'books', 'description', 'title',
173             'book_slugs', 'authors', 'author_slugs'
174         ]
175
176     def update(self, instance, validated_data):
177         instance = super().update(instance, validated_data)
178         author_slugs = validated_data.get('author_slugs', '').strip().split()
179         if author_slugs:
180             authors = Tag.objects.filter(
181                 category='author',
182                 slug__in=author_slugs
183             )
184         else:
185             authors = []
186         instance.authors.set(authors)
187         return instance
188
189
190 class FragmentSerializer(serializers.ModelSerializer):
191     book = BookSerializer()
192     url = AbsoluteURLField()
193     href = AbsoluteURLField(source='get_api_url')
194
195     class Meta:
196         model = Fragment
197         fields = ['book', 'url', 'anchor', 'href']
198
199
200 class FragmentDetailSerializer(serializers.ModelSerializer):
201     book = BookSerializer()
202     url = AbsoluteURLField()
203     themes = TagSerializer(many=True)
204
205     class Meta:
206         model = Fragment
207         fields = ['book', 'anchor', 'text', 'url', 'themes']