+
+
+class TagCategoryView(LegacyListAPIView):
+ serializer_class = serializers.TagSerializer
+
+ def get_queryset(self):
+ category = self.kwargs['category']
+ tags = Tag.objects.filter(category=category).exclude(items=None).order_by('slug')
+
+ after = self.request.query_params.get('after')
+ count = self.request.query_params.get('count')
+ if after:
+ tags = tags.filter(slug__gt=after)
+ if count:
+ tags = tags[:count]
+
+ return tags
+
+class AuthorList(ListAPIView):
+ serializer_class = serializers.AuthorSerializer
+ queryset = Tag.objects.filter(category='author')
+
+class AuthorView(RetrieveAPIView):
+ serializer_class = serializers.AuthorSerializer
+ queryset = Tag.objects.filter(category='author')
+ lookup_field = 'slug'
+
+class EpochList(ListAPIView):
+ serializer_class = serializers.EpochSerializer
+ queryset = Tag.objects.filter(category='epoch')
+
+class EpochView(RetrieveAPIView):
+ serializer_class = serializers.EpochSerializer
+ queryset = Tag.objects.filter(category='epoch')
+ lookup_field = 'slug'
+
+class GenreList(ListAPIView):
+ serializer_class = serializers.GenreSerializer
+ queryset = Tag.objects.filter(category='genre')
+
+class GenreView(RetrieveAPIView):
+ serializer_class = serializers.GenreSerializer
+ queryset = Tag.objects.filter(category='genre')
+ lookup_field = 'slug'
+
+class KindList(ListAPIView):
+ serializer_class = serializers.KindSerializer
+ queryset = Tag.objects.filter(category='kind')
+
+class KindView(RetrieveAPIView):
+ serializer_class = serializers.KindSerializer
+ queryset = Tag.objects.filter(category='kind')
+ lookup_field = 'slug'
+
+class ThemeList(ListAPIView):
+ serializer_class = serializers.ThemeSerializer
+ queryset = Tag.objects.filter(category='theme')
+
+class ThemeView(RetrieveAPIView):
+ serializer_class = serializers.ThemeSerializer
+ queryset = Tag.objects.filter(category='theme')
+ lookup_field = 'slug'
+
+
+class TagView(RetrieveAPIView):
+ permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
+ serializer_class = serializers.TagDetailSerializer
+ queryset = Tag.objects.all()
+
+ def get_object(self):
+ try:
+ return get_object_or_404(
+ Tag,
+ category=self.kwargs['category'],
+ slug=self.kwargs['slug']
+ )
+ except Http404:
+ if self.request.method == 'POST':
+ return Tag(
+ category=self.kwargs['category'],
+ slug=self.kwargs['slug']
+ )
+ else:
+ raise
+
+ def post(self, request, **kwargs):
+ data = json.loads(request.POST.get('data'))
+ fields = {
+ "name_pl": "name_pl",
+ "description_pl": "description_pl",
+ "plural": "plural",
+ "is_epoch_specific": "genre_epoch_specific",
+ "collective_noun": "collective_noun",
+ "adjective_feminine_singular": "adjective_feminine_singular",
+ "adjective_nonmasculine_plural": "adjective_nonmasculine_plural",
+ "genitive": "genitive",
+ "collective_noun": "collective_noun",
+ "gazeta_link": "gazeta_link",
+ "culturepl_link": "culturepl_link",
+ "wiki_link_pl": "wiki_link_pl",
+ "photo_attribution": "photo_attribution",
+ }
+ obj = self.get_object()
+ updated = set()
+ for data_field, model_field in fields.items():
+ value = data.get(data_field)
+ if value:
+ if obj.category == 'author' and model_field == 'name_pl':
+ obj.sort_key = sortify(value.lower())
+ updated.add('sort_key')
+ value = ' '.join(reversed([t.strip() for t in value.split(',', 1)]))
+ setattr(obj, model_field, value)
+ updated.add(model_field)
+ if data.get('photo'):
+ response = urlopen(data['photo'])
+ ext = response.headers.get('Content-Type', '').rsplit('/', 1)[-1]
+ obj.photo.save(
+ "{}.{}".format(self.kwargs['slug'], ext),
+ ContentFile(response.read()),
+ save=False,
+ )
+ updated.add('photo')
+
+ if obj.pk:
+ obj.save(update_fields=updated, quick=True)
+ else:
+ obj.save()
+ return Response({})
+
+
+@vary_on_auth # Because of 'liked'.
+class FragmentList(LegacyListAPIView):
+ serializer_class = serializers.FragmentSerializer
+
+ def get_queryset(self):
+ try:
+ tags, ancestors = read_tags(
+ self.kwargs['tags'],
+ self.request,
+ allowed={'author', 'epoch', 'kind', 'genre', 'book', 'theme'}
+ )
+ except ValueError:
+ raise Http404
+ return Fragment.tagged.with_all(tags).filter(book__findable=True).select_related('book')
+
+
+@vary_on_auth # Because of 'liked'.
+class FragmentView(RetrieveAPIView):
+ serializer_class = serializers.FragmentDetailSerializer
+
+ def get_object(self):
+ return get_object_or_404(
+ Fragment,
+ book__slug=self.kwargs['book'],
+ anchor=self.kwargs['anchor']
+ )
+
+
+class SuggestedTags(ListAPIView):
+ serializer_class = serializers.FilterTagSerializer
+
+ def get_queryset(self):
+ tag_ids = self.request.GET.getlist('tag', [])
+ search = self.request.GET.get('search')
+ tags = [get_object_or_404(Tag, id=tid) for tid in tag_ids]
+ related_tags = list(t.id for t in get_top_level_related_tags(tags))
+ tags = Tag.objects.filter(id__in=related_tags)
+ if search:
+ tags = tags.filter(name__icontains=search)
+ return tags
+
+
+class BookFragmentView(RetrieveAPIView):
+ serializer_class = serializers.FragmentSerializer2
+
+ def get_object(self):
+ book = get_object_or_404(Book, slug=self.kwargs['slug'])
+ return book.choose_fragment()
+
+
+class BookMediaView(ListAPIView):
+ serializer_class = serializers.MediaSerializer2
+ pagination_class = None
+
+ def get_queryset(self):
+ return BookMedia.objects.filter(book__slug=self.kwargs['slug'], type=self.kwargs['type']).order_by('index')
+
+
+from .tojson import conv
+from lxml import etree
+from rest_framework.views import APIView
+class BookJsonView(APIView):
+ def get(self, request, slug):
+ book = get_object_or_404(Book, slug=slug)
+ js = conv(etree.parse(book.xml_file.path))
+ return JsonResponse(js, json_dumps_params={'ensure_ascii': False})
+