+ def get_absolute_url(self):
+ return '%s#m%s' % (reverse('book_text', kwargs={'slug': self.book.slug}), self.anchor)
+
+ def short_html(self):
+ key = '_short_html_%s' % get_language()
+ short_html = getattr(self, key)
+ if short_html and len(short_html):
+ return mark_safe(short_html)
+ else:
+ setattr(self, key, unicode(render_to_string('catalogue/fragment_short.html',
+ {'fragment': self})))
+ self.save()
+ return mark_safe(getattr(self, key))
+
+
+class BookStub(models.Model):
+ title = models.CharField(_('title'), max_length=120)
+ author = models.CharField(_('author'), max_length=120)
+ pd = models.IntegerField(_('goes to public domain'), null=True, blank=True)
+ slug = models.SlugField(_('slug'), max_length=120, unique=True, db_index=True)
+ translator = models.TextField(_('translator'), blank=True)
+ translator_death = models.TextField(_('year of translator\'s death'), blank=True)
+
+ class Meta:
+ ordering = ('title',)
+ verbose_name = _('book stub')
+ verbose_name_plural = _('book stubs')
+
+ def __unicode__(self):
+ return self.title
+
+ @permalink
+ def get_absolute_url(self):
+ return ('catalogue.views.book_detail', [self.slug])
+
+ def in_pd(self):
+ return self.pd is not None and self.pd <= datetime.now().year
+
+ @property
+ def name(self):
+ return self.title
+
+
+class FileRecord(models.Model):
+ slug = models.SlugField(_('slug'), max_length=120, db_index=True)
+ type = models.CharField(_('type'), max_length=20, db_index=True)
+ sha1 = models.CharField(_('sha-1 hash'), max_length=40)
+ time = models.DateTimeField(_('time'), auto_now_add=True)
+
+ class Meta:
+ ordering = ('-time','-slug', '-type')
+ verbose_name = _('file record')
+ verbose_name_plural = _('file records')
+
+ def __unicode__(self):
+ return "%s %s.%s" % (self.sha1, self.slug, self.type)
+
+
+def _tags_updated_handler(sender, affected_tags, **kwargs):
+ # reset tag global counter
+ Tag.objects.filter(pk__in=[tag.pk for tag in affected_tags]).update(book_count=None)
+
+ # if book tags changed, reset book tag counter
+ if isinstance(sender, Book) and \
+ Tag.objects.filter(pk__in=(tag.pk for tag in affected_tags)).\
+ exclude(category__in=('book', 'theme', 'set')).count():
+ sender.reset_tag_counter()
+ # if fragment theme changed, reset book theme counter
+ elif isinstance(sender, Fragment) and \
+ Tag.objects.filter(pk__in=(tag.pk for tag in affected_tags)).\
+ filter(category='theme').count():
+ sender.book.reset_theme_counter()
+tags_updated.connect(_tags_updated_handler)
+