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
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
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, )
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
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_to_response('catalogue/tagged_object_list.html', result, context_instance=RequestContext(request))