1 from django.http import Http404, HttpResponse
2 from rest_framework.generics import ListAPIView, RetrieveAPIView, get_object_or_404
3 from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
4 from rest_framework import status
5 from paypal.permissions import IsSubscribed
6 from api.handlers import read_tags
7 from .helpers import books_after, order_books
8 from . import serializers
9 from catalogue.models import Book, Collection, Tag, Fragment
10 from catalogue.models.tag import prefetch_relations
13 class CollectionList(ListAPIView):
14 queryset = Collection.objects.all()
15 serializer_class = serializers.CollectionListSerializer
18 class CollectionDetail(RetrieveAPIView):
19 queryset = Collection.objects.all()
21 serializer_class = serializers.CollectionSerializer
24 class BookList(ListAPIView):
25 permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
26 queryset = Book.objects.none() # Required for DjangoModelPermissions
27 serializer_class = serializers.BaseBookSerializer
29 def get_queryset(self):
31 tags, ancestors = read_tags(
32 self.kwargs['tags'], self.request,
33 allowed=('author', 'epoch', 'kind', 'genre')
38 new_api = self.request.query_params.get('new_api')
39 after = self.request.query_params.get('after', self.kwargs.get('after'))
40 count = self.request.query_params.get('count', self.kwargs.get('count'))
43 if self.kwargs.get('top_level'):
44 books = Book.tagged_top_level(tags)
49 books = Book.tagged.with_all(tags)
51 books = Book.objects.all()
52 books = order_books(books, new_api)
54 if self.kwargs.get('top_level'):
55 books = books.filter(parent=None)
56 if self.kwargs.get('audiobooks'):
57 books = books.filter(media__type='mp3').distinct()
58 if self.kwargs.get('daisy'):
59 books = books.filter(media__type='daisy').distinct()
60 if self.kwargs.get('recommended'):
61 books = books.filter(recommended=True)
62 if self.kwargs.get('newest'):
63 books = books.order_by('-created_at')
66 books = books_after(books, after, new_api)
68 prefetch_relations(books, 'author')
69 prefetch_relations(books, 'genre')
70 prefetch_relations(books, 'kind')
71 prefetch_relations(books, 'epoch')
78 def post(self, request):
80 data = json.loads(request.POST.get('data'))
81 form = BookImportForm(data)
84 return Response({}, status=status.HTTP_201_CREATED)
89 class BookDetail(RetrieveAPIView):
90 queryset = Book.objects.all()
92 serializer_class = serializers.BookDetailSerializer
95 class Preview(ListAPIView):
96 queryset = Book.objects.filter(preview=True)
97 serializer_class = serializers.BookPreviewSerializer
100 class EpubView(RetrieveAPIView):
101 queryset = Book.objects.all()
102 lookup_field = 'slug'
103 permission_classes = [IsSubscribed]
105 def get(self, *args, **kwargs):
106 return HttpResponse(self.get_object().get_media('epub'))
109 class TagCategoryView(ListAPIView):
110 serializer_class = serializers.TagSerializer
112 def get_queryset(self):
113 category = self.kwargs['category']
114 tags = Tag.objects.filter(category=category).exclude(items=None).order_by('slug')
115 if self.request.query_params.get('book_only') == 'true':
116 tags = tags.filter(for_books=True)
117 if self.request.GET.get('picture_only') == 'true':
118 tags = filter(for_pictures=True)
120 after = self.request.query_params.get('after')
121 count = self.request.query_params.get('count')
123 tags = tags.filter(slug__gt=after)
130 class TagView(RetrieveAPIView):
131 serializer_class = serializers.TagDetailSerializer
133 def get_object(self):
134 return get_object_or_404(
136 category=self.kwargs['category'],
137 slug=self.kwargs['slug']
141 class FragmentList(ListAPIView):
142 serializer_class = serializers.FragmentSerializer
144 def get_queryset(self):
146 tags, ancestors = read_tags(
149 allowed={'author', 'epoch', 'kind', 'genre', 'book', 'theme'}
153 return Fragment.tagged.with_all(tags).select_related('book')
156 class FragmentView(RetrieveAPIView):
157 serializer_class = serializers.FragmentDetailSerializer
159 def get_object(self):
160 return get_object_or_404(
162 book__slug=self.kwargs['book'],
163 anchor=self.kwargs['anchor']