+
+ _tag_counter = JSONField(null=True, editable=False)
+ _theme_counter = JSONField(null=True, editable=False)
+
+ class AlreadyExists(Exception):
+ pass
+
+ class Meta:
+ ordering = ('title',)
+ verbose_name = _('book')
+ verbose_name_plural = _('books')
+
+ def __unicode__(self):
+ return self.title
+
+ def save(self, force_insert=False, force_update=False, reset_short_html=True, refresh_mp3=True, **kwargs):
+ if reset_short_html:
+ # Reset _short_html during save
+ update = {}
+ for key in filter(lambda x: x.startswith('_short_html'), self.__dict__):
+ update[key] = ''
+ self.__setattr__(key, '')
+ # Fragment.short_html relies on book's tags, so reset it here too
+ self.fragments.all().update(**update)
+
+ book = super(Book, self).save(force_insert, force_update)
+
+ if refresh_mp3 and self.mp3_file:
+ print self.mp3_file, self.mp3_file.path
+ extra_info = self.get_extra_info_value()
+ extra_info.update(self.get_mp3_info())
+ self.set_extra_info_value(extra_info)
+ book = super(Book, self).save(force_insert, force_update)
+
+ return book
+
+ @permalink
+ def get_absolute_url(self):
+ return ('catalogue.views.book_detail', [self.slug])
+
+ @property
+ def name(self):
+ return self.title
+
+ def book_tag_slug(self):
+ return ('l-' + self.slug)[:120]
+
+ def book_tag(self):
+ slug = self.book_tag_slug()
+ book_tag, created = Tag.objects.get_or_create(slug=slug, category='book')
+ if created:
+ book_tag.name = self.title[:50]
+ book_tag.sort_key = slug
+ book_tag.save()
+ return book_tag
+