author/title match ordering in api filter-books + fix lektura/audiobook filters
[wolnelektury.git] / src / catalogue / models / book.py
index 0ed9716..00921b8 100644 (file)
@@ -13,7 +13,7 @@ from django.db.models import permalink
 import django.dispatch
 from django.contrib.contenttypes.fields import GenericRelation
 from django.core.urlresolvers import reverse
 import django.dispatch
 from django.contrib.contenttypes.fields import GenericRelation
 from django.core.urlresolvers import reverse
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import ugettext_lazy as _, get_language
 import jsonfield
 from fnpdjango.storage import BofhFileSystemStorage
 from ssify import flush_ssi_includes
 import jsonfield
 from fnpdjango.storage import BofhFileSystemStorage
 from ssify import flush_ssi_includes
@@ -22,6 +22,7 @@ from catalogue import constants
 from catalogue.fields import EbookField
 from catalogue.models import Tag, Fragment, BookMedia
 from catalogue.utils import create_zip, gallery_url, gallery_path
 from catalogue.fields import EbookField
 from catalogue.models import Tag, Fragment, BookMedia
 from catalogue.utils import create_zip, gallery_url, gallery_path
+from catalogue.models.tag import prefetched_relations
 from catalogue import app_settings
 from catalogue import tasks
 from wolnelektury.utils import makedirs
 from catalogue import app_settings
 from catalogue import tasks
 from wolnelektury.utils import makedirs
@@ -59,6 +60,8 @@ class Book(models.Model):
     extra_info = jsonfield.JSONField(_('extra information'), default={})
     gazeta_link = models.CharField(blank=True, max_length=240)
     wiki_link = models.CharField(blank=True, max_length=240)
     extra_info = jsonfield.JSONField(_('extra information'), default={})
     gazeta_link = models.CharField(blank=True, max_length=240)
     wiki_link = models.CharField(blank=True, max_length=240)
+    print_on_demand = models.BooleanField(_('print on demand'), default=False)
+    recommended = models.BooleanField(_('recommended'), default=False)
 
     # files generated during publication
     cover = EbookField(
 
     # files generated during publication
     cover = EbookField(
@@ -78,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)
 
     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)
     objects = models.Manager()
     tagged = managers.ModelTaggedItemManager(Tag)
     tags = managers.TagDescriptor(Tag)
@@ -109,8 +115,29 @@ class Book(models.Model):
     def authors(self):
         return self.tags.filter(category='author')
 
     def authors(self):
         return self.tags.filter(category='author')
 
+    def tag_unicode(self, category):
+        relations = prefetched_relations(self, category)
+        if relations:
+            return ', '.join(rel.tag.name for rel in relations)
+        else:
+            return ', '.join(self.tags.filter(category=category).values_list('name', flat=True))
+
     def author_unicode(self):
     def author_unicode(self):
-        return ", ".join(self.authors().values_list('name', flat=True))
+        return self.cached_author
+
+    def translator(self):
+        translators = self.extra_info.get('translators')
+        if not translators:
+            return None
+        if len(translators) > 3:
+            translators = translators[:2]
+            others = ' i inni'
+        else:
+            others = ''
+        return ', '.join(u'\xa0'.join(reversed(translator.split(', ', 1))) for translator in translators) + others
+
+    def cover_source(self):
+        return self.extra_info.get('cover_source', self.parent.cover_source() if self.parent else '')
 
     def save(self, force_insert=False, force_update=False, **kwargs):
         from sortify import sortify
 
     def save(self, force_insert=False, force_update=False, **kwargs):
         from sortify import sortify
@@ -124,6 +151,9 @@ class Book(models.Model):
             author = u''
         self.sort_key_author = author
 
             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
         ret = super(Book, self).save(force_insert, force_update, **kwargs)
 
         return ret
@@ -378,6 +408,7 @@ class Book(models.Model):
         for child in notify_cover_changed:
             child.parent_cover_changed()
 
         for child in notify_cover_changed:
             child.parent_cover_changed()
 
+        book.save()  # update sort_key_author
         cls.published.send(sender=cls, instance=book)
         return book
 
         cls.published.send(sender=cls, instance=book)
         return book
 
@@ -491,6 +522,13 @@ class Book(models.Model):
             names = [tag[0] for tag in names]
         return ', '.join(names)
 
             names = [tag[0] for tag in names]
         return ', '.join(names)
 
+    def publisher(self):
+        publisher = self.extra_info['publisher']
+        if isinstance(publisher, basestring):
+            return publisher
+        elif isinstance(publisher, list):
+            return ', '.join(publisher)
+
     @classmethod
     def tagged_top_level(cls, tags):
         """ Returns top-level books tagged with `tags`.
     @classmethod
     def tagged_top_level(cls, tags):
         """ Returns top-level books tagged with `tags`.
@@ -544,6 +582,7 @@ class Book(models.Model):
         "SP": (1, u"szkoła podstawowa"),
         "SP1": (1, u"szkoła podstawowa"),
         "SP2": (1, u"szkoła podstawowa"),
         "SP": (1, u"szkoła podstawowa"),
         "SP1": (1, u"szkoła podstawowa"),
         "SP2": (1, u"szkoła podstawowa"),
+        "SP3": (1, u"szkoła podstawowa"),
         "P": (1, u"szkoła podstawowa"),
         "G": (2, u"gimnazjum"),
         "L": (3, u"liceum"),
         "P": (1, u"szkoła podstawowa"),
         "G": (2, u"gimnazjum"),
         "L": (3, u"liceum"),
@@ -576,6 +615,13 @@ class Book(models.Model):
         else:
             return None
 
         else:
             return None
 
+    def fragment_data(self):
+        fragment = self.choose_fragment()
+        if fragment:
+            return {'title': fragment.book.pretty_title(), 'html': fragment.get_short_text()}
+        else:
+            return None
+
     def update_popularity(self):
         count = self.tags.filter(category='set').values('user').order_by('user').distinct().count()
         try:
     def update_popularity(self):
         count = self.tags.filter(category='set').values('user').order_by('user').distinct().count()
         try:
@@ -585,6 +631,9 @@ class Book(models.Model):
         except BookPopularity.DoesNotExist:
             BookPopularity.objects.create(book=self, count=count)
 
         except BookPopularity.DoesNotExist:
             BookPopularity.objects.create(book=self, count=count)
 
+    def ridero_link(self):
+        return 'https://ridero.eu/%s/books/wl_%s/' % (get_language(), self.slug.replace('-', '_'))
+
 
 def add_file_fields():
     for format_ in Book.formats:
 
 def add_file_fields():
     for format_ in Book.formats: