Example #1
0
    def get_queryset(self):
        key_sep = '$'
        search_string = self.request.query_params.get('search')
        is_lektura = self.parse_bool(self.request.query_params.get('lektura'))
        is_audiobook = self.parse_bool(self.request.query_params.get('audiobook'))
        preview = self.parse_bool(self.request.query_params.get('preview'))

        new_api = self.request.query_params.get('new_api')
        after = self.request.query_params.get('after')
        count = int(self.request.query_params.get('count', 50))
        books = order_books(Book.objects.distinct(), new_api)
        if is_lektura is not None:
            books = books.filter(has_audience=is_lektura)
        if is_audiobook is not None:
            if is_audiobook:
                books = books.filter(media__type='mp3')
            else:
                books = books.exclude(media__type='mp3')
        if preview is not None:
            books = books.filter(preview=preview)
        for category in book_tag_categories:
            category_plural = category + 's'
            if category_plural in self.request.query_params:
                slugs = self.request.query_params[category_plural].split(',')
                tags = Tag.objects.filter(category=category, slug__in=slugs)
                books = Book.tagged.with_any(tags, books)
        if (search_string is not None) and len(search_string) < 3:
            search_string = None
        if search_string:
            search_string = re_escape(search_string)
            books_author = books.filter(cached_author__iregex=r'\m' + search_string)
            books_title = books.filter(title__iregex=r'\m' + search_string)
            books_title = books_title.exclude(id__in=list(books_author.values_list('id', flat=True)))
            if after and (key_sep in after):
                which, key = after.split(key_sep, 1)
                if which == 'title':
                    book_lists = [(books_after(books_title, key, new_api), 'title')]
                else:  # which == 'author'
                    book_lists = [(books_after(books_author, key, new_api), 'author'), (books_title, 'title')]
            else:
                book_lists = [(books_author, 'author'), (books_title, 'title')]
        else:
            if after and key_sep in after:
                which, key = after.split(key_sep, 1)
                books = books_after(books, key, new_api)
            book_lists = [(books, 'book')]

        filtered_books = []
        for book_list, label in book_lists:
            for category in book_tag_categories:
                book_list = prefetch_relations(book_list, category)
            remaining_count = count - len(filtered_books)
            for book in book_list[:remaining_count]:
                book.key = '%s%s%s' % (
                    label, key_sep, book.slug if not new_api else book.full_sort_key())
                filtered_books.append(book)
            if len(filtered_books) == count:
                break

        return filtered_books
Example #2
0
    def get_queryset(self):
        try:
            tags, ancestors = read_tags(
                self.kwargs.get('tags', ''), self.request,
                allowed=('author', 'epoch', 'kind', 'genre')
            )
        except ValueError:
            raise Http404

        new_api = self.request.query_params.get('new_api')
        after = self.request.query_params.get('after', self.kwargs.get('after'))
        count = self.request.query_params.get('count', self.kwargs.get('count'))
        if count:
            try:
                count = int(count)
            except TypeError:
                raise Http404  # Fixme

        if tags:
            if self.kwargs.get('top_level'):
                books = Book.tagged_top_level(tags)
                if not books:
                    raise Http404
                return books
            else:
                books = Book.tagged.with_all(tags)
        else:
            books = Book.objects.all()
        books = order_books(books, new_api)

        if self.kwargs.get('top_level'):
            books = books.filter(parent=None)
        if self.kwargs.get('audiobooks'):
            books = books.filter(media__type='mp3').distinct()
        if self.kwargs.get('daisy'):
            books = books.filter(media__type='daisy').distinct()
        if self.kwargs.get('recommended'):
            books = books.filter(recommended=True)
        if self.kwargs.get('newest'):
            books = books.order_by('-created_at')

        if after:
            books = books_after(books, after, new_api)

        prefetch_relations(books, 'author')
        prefetch_relations(books, 'genre')
        prefetch_relations(books, 'kind')
        prefetch_relations(books, 'epoch')

        if count:
            books = books[:count]

        return books
Example #3
0
def object_list(request, objects, fragments=None, related_tags=None, tags=None, list_type='books', extra=None):
    if not tags:
        tags = []
    tag_ids = [tag.pk for tag in tags]

    related_tag_lists = []
    if related_tags:
        related_tag_lists.append(related_tags)
    else:
        related_tag_lists.append(
            Tag.objects.usage_for_queryset(objects, counts=True).exclude(category='set').exclude(pk__in=tag_ids))
    if not (extra and extra.get('theme_is_set')):
        if fragments is None:
            if list_type == 'gallery':
                fragments = PictureArea.objects.filter(picture__in=objects)
            else:
                fragments = Fragment.objects.filter(book__in=objects)
        related_tag_lists.append(
            Tag.objects.usage_for_queryset(fragments, counts=True).filter(category='theme').exclude(pk__in=tag_ids)
            .only('name', 'sort_key', 'category', 'slug'))
        if isinstance(objects, QuerySet):
            objects = prefetch_relations(objects, 'author')

    categories = split_tags(*related_tag_lists)

    objects = list(objects)

    if not objects and len(tags) == 1 and list_type == 'books':
        if PictureArea.tagged.with_any(tags).exists() or Picture.tagged.with_any(tags).exists():
            return redirect('tagged_object_list_gallery', '/'.join(tag.url_chunk for tag in tags))

    if len(objects) > 3:
        best = random.sample(objects, 3)
    else:
        best = objects

    result = {
        'object_list': objects,
        'categories': categories,
        'list_type': list_type,
        'tags': tags,

        'formats_form': forms.DownloadFormatsForm(),
        'best': best,
        'active_menu_item': list_type,
    }
    if extra:
        result.update(extra)
    return render(
        request,
        'catalogue/tagged_object_list.html', result,
    )
Example #4
0
    def read(self, request, tags=None, top_level=False, audiobooks=False, daisy=False, pk=None):
        """ Lists all books with given tags.

        :param tags: filtering tags; should be a path of categories
             and slugs, i.e.: authors/an-author/epoch/an-epoch/
        :param top_level: if True and a book is included in the results,
             it's children are aren't. By default all books matching the tags
             are returned.
        """
        if pk is not None:
            try:
                return Book.objects.get(pk=pk)
            except Book.DoesNotExist:
                return rc.NOT_FOUND

        try:
            tags, _ancestors = read_tags(tags, allowed=book_tag_categories)
        except ValueError:
            return rc.NOT_FOUND

        if tags:
            if top_level:
                books = Book.tagged_top_level(tags)
                return books if books else rc.NOT_FOUND
            else:
                books = Book.tagged.with_all(tags)
        else:
            books = Book.objects.all()

        if top_level:
            books = books.filter(parent=None)
        if audiobooks:
            books = books.filter(media__type='mp3').distinct()
        if daisy:
            books = books.filter(media__type='daisy').distinct()

        books = books.only('slug', 'title', 'cover', 'cover_thumb')
        for category in book_tag_categories:
            books = prefetch_relations(books, category)
        if books:
            return books
        else:
            return rc.NOT_FOUND