From 4b30aa4337497a5b225527900d67868912d3715e Mon Sep 17 00:00:00 2001 From: Jan Szejko Date: Tue, 31 Oct 2017 13:38:04 +0100 Subject: [PATCH] add to api: filter for app --- src/api/handlers.py | 32 +++++++++++++++- src/api/urls.py | 4 ++ .../migrations/0016_auto_20171031_1232.py | 37 +++++++++++++++++++ src/catalogue/models/book.py | 8 +++- 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/catalogue/migrations/0016_auto_20171031_1232.py diff --git a/src/api/handlers.py b/src/api/handlers.py index 6b1d8089d..a869e5845 100644 --- a/src/api/handlers.py +++ b/src/api/handlers.py @@ -172,7 +172,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): @piwik_track def read(self, request, tags=None, top_level=False, audiobooks=False, daisy=False, pk=None, - recommended=False, newest=False, + recommended=False, newest=False, books=None, after=None, before=None, count=None): """ Lists all books with given tags. @@ -200,7 +200,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): else: books = Book.tagged.with_all(tags) else: - books = Book.objects.all() + books = books if books is not None else Book.objects.all() books = books.order_by('slug') if top_level: @@ -261,6 +261,34 @@ class EBooksHandler(AnonymousBooksHandler): fields = ('author', 'href', 'title', 'cover') + tuple(Book.ebook_formats) + ('slug',) +class FilterBooksHandler(AnonymousBooksHandler): + fields = book_tag_categories + ['href', 'title', 'url', 'cover', 'cover_thumb', 'slug'] + + def read(self, request, title_part=None, author_part=None, is_lektura=None, is_audiobook=None, + after=None, before=None, count=None): + if count is None: + count = 50 + if is_lektura in ('true', 'false'): + is_lektura = is_lektura == 'true' + else: + is_lektura = None + if is_audiobook in ('true', 'false'): + is_audiobook = is_audiobook == 'true' + books = Book.objects.distinct() + if title_part: + books = books.filter(title__icontains=title_part) + if author_part is not None: + books = books.filter(cached_author__icontains=author_part) + 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') + return super(FilterBooksHandler, self).read(request, books=books, after=after, before=before, count=count) + + # add categorized tags fields for Book def _tags_getter(category): @classmethod diff --git a/src/api/urls.py b/src/api/urls.py index 7d984634d..8a9965d75 100644 --- a/src/api/urls.py +++ b/src/api/urls.py @@ -17,6 +17,7 @@ book_list_resource = CsrfExemptResource(handler=handlers.BooksHandler, authentic ebook_list_resource = Resource(handler=handlers.EBooksHandler) # book_list_resource = Resource(handler=handlers.BooksHandler) book_resource = Resource(handler=handlers.BookDetailHandler) +filter_book_resource = Resource(handler=handlers.FilterBooksHandler) collection_resource = Resource(handler=handlers.CollectionDetailHandler) collection_list_resource = Resource(handler=handlers.CollectionsHandler) @@ -92,6 +93,9 @@ urlpatterns = patterns( url(r'^recommended/' + paginate_re, book_list_resource, {"recommended": True}, name='api_recommended_list'), url(r'^newest/', book_list_resource, {"newest": True, "count": 20}, name='api_newest_list'), + url(r'^filter-books/(?:title-part/(?P[^/]+)/)?(?:author-part/(?P[^/]+)/)?' + r'(?:lektura/(?P(?:true|false))/)?(?:audiobook/(?P(?:true|false))/)?' + + paginate_re, filter_book_resource, name='api_filter_books'), url(r'^pictures/$', picture_resource), diff --git a/src/catalogue/migrations/0016_auto_20171031_1232.py b/src/catalogue/migrations/0016_auto_20171031_1232.py new file mode 100644 index 000000000..1dbee6085 --- /dev/null +++ b/src/catalogue/migrations/0016_auto_20171031_1232.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +def refresh_books(apps, schema_editor): + Book = apps.get_model('catalogue', 'Book') + TagRelation = apps.get_model('catalogue', 'TagRelation') + db_alias = schema_editor.connection.alias + for book in Book.objects.using(db_alias).all(): + book.cached_author = ', '.join( + TagRelation.objects.filter(content_type__model='book', object_id=book.id, tag__category='author') + .values_list('tag__name', flat=True)) + book.has_audience = 'audience' in book.extra_info + book.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0015_book_recommended'), + ] + + operations = [ + migrations.AddField( + model_name='book', + name='cached_author', + field=models.CharField(db_index=True, max_length=240, blank=True), + ), + migrations.AddField( + model_name='book', + name='has_audience', + field=models.BooleanField(default=False), + ), + migrations.RunPython(refresh_books, lambda apps, schema_editor: None), + ] diff --git a/src/catalogue/models/book.py b/src/catalogue/models/book.py index b0c63a0ec..69d71aef2 100644 --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@ -81,6 +81,9 @@ class Book(models.Model): parent = models.ForeignKey('self', blank=True, null=True, related_name='children') ancestor = models.ManyToManyField('self', blank=True, editable=False, related_name='descendant', symmetrical=False) + cached_author = models.CharField(blank=True, max_length=240, db_index=True) + has_audience = models.BooleanField(default=False) + objects = models.Manager() tagged = managers.ModelTaggedItemManager(Tag) tags = managers.TagDescriptor(Tag) @@ -120,7 +123,7 @@ class Book(models.Model): return ', '.join(self.tags.filter(category=category).values_list('name', flat=True)) def author_unicode(self): - return self.tag_unicode('author') + return self.cached_author def translator(self): translators = self.extra_info.get('translators') @@ -145,6 +148,9 @@ class Book(models.Model): author = u'' self.sort_key_author = author + self.cached_author = self.tag_unicode('author') + self.has_audience = 'audience' in self.extra_info + ret = super(Book, self).save(force_insert, force_update, **kwargs) return ret -- 2.20.1