from django.http import Http404, HttpResponse
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
+from django_filters import rest_framework as dfilters
+from rest_framework import filters
from rest_framework.generics import (ListAPIView, RetrieveAPIView,
RetrieveUpdateAPIView, get_object_or_404)
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
from api.handlers import read_tags
from api.utils import vary_on_auth
from catalogue.forms import BookImportForm
+from catalogue.helpers import get_top_level_related_tags
from catalogue.models import Book, Collection, Tag, Fragment, BookMedia
from catalogue.models.tag import prefetch_relations
from club.models import Membership
book_tag_categories = ['author', 'epoch', 'kind', 'genre']
+class LegacyListAPIView(ListAPIView):
+ pagination_class = None
+
+
class CreateOnPutMixin:
'''
Creates a new model instance when PUTting a nonexistent resource.
raise
-class CollectionList(ListAPIView):
+class CollectionList(LegacyListAPIView):
queryset = Collection.objects.filter(listed=True)
serializer_class = serializers.CollectionListSerializer
@vary_on_auth # Because of 'liked'.
-class BookList(ListAPIView):
+class BookList(LegacyListAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
queryset = Book.objects.none() # Required for DjangoModelPermissions
serializer_class = serializers.BookListSerializer
return Response({}, status=status.HTTP_201_CREATED)
+class BookFilter(dfilters.FilterSet):
+ sort = dfilters.OrderingFilter(
+ fields=(
+ ('sort_key_author', 'alpha'),
+ ('popularity', 'popularity'),
+ )
+ )
+ tag = dfilters.ModelMultipleChoiceFilter(
+ field_name='tag_relations__tag',
+ queryset=Tag.objects.filter(category__in=('author', 'epoch', 'genre', 'kind')),
+ conjoined=True,
+ )
+
+
+class BookList2(ListAPIView):
+ permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
+ queryset = Book.objects.none() # Required for DjangoModelPermissions
+ serializer_class = serializers.BookSerializer2
+ filter_backends = (
+ dfilters.DjangoFilterBackend,
+ filters.SearchFilter,
+ )
+ filterset_class = BookFilter
+ search_fields = [
+ 'title',
+ ]
+
+ def get_queryset(self):
+ books = Book.objects.all()
+ books = books.filter(findable=True)
+ books = order_books(books, True)
+
+ 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()
serializer_class = serializers.BookDetailSerializer
+class BookDetail2(RetrieveAPIView):
+ queryset = Book.objects.all()
+ lookup_field = 'slug'
+ serializer_class = serializers.BookSerializer2
+
+
@vary_on_auth # Because of embargo links.
class EbookList(BookList):
serializer_class = serializers.EbookSerializer
@method_decorator(never_cache, name='dispatch')
-class Preview(ListAPIView):
+class Preview(LegacyListAPIView):
#queryset = Book.objects.filter(preview=True)
serializer_class = serializers.BookPreviewSerializer
@vary_on_auth # Because of 'liked'.
-class FilterBookList(ListAPIView):
+class FilterBookList(LegacyListAPIView):
serializer_class = serializers.FilterBookListSerializer
def parse_bool(self, s):
return HttpResponse(self.get_object().get_media('epub'))
-class TagCategoryView(ListAPIView):
+class TagCategoryView(LegacyListAPIView):
serializer_class = serializers.TagSerializer
def get_queryset(self):
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 TagView(RetrieveAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
@vary_on_auth # Because of 'liked'.
-class FragmentList(ListAPIView):
+class FragmentList(LegacyListAPIView):
serializer_class = serializers.FragmentSerializer
def get_queryset(self):
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()
+