move short_html to cache
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Thu, 1 Sep 2011 12:08:09 +0000 (14:08 +0200)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Thu, 1 Sep 2011 12:08:09 +0000 (14:08 +0200)
apps/catalogue/migrations/0015_auto__del_field_book__short_html_en__del_field_book__short_html_es__de.py [new file with mode: 0644]
apps/catalogue/models.py
wolnelektury/translation.py

diff --git a/apps/catalogue/migrations/0015_auto__del_field_book__short_html_en__del_field_book__short_html_es__de.py b/apps/catalogue/migrations/0015_auto__del_field_book__short_html_en__del_field_book__short_html_es__de.py
new file mode 100644 (file)
index 0000000..72acef9
--- /dev/null
@@ -0,0 +1,244 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Deleting field 'Book._short_html_en'
+        db.delete_column('catalogue_book', '_short_html_en')
+
+        # Deleting field 'Book._short_html_es'
+        db.delete_column('catalogue_book', '_short_html_es')
+
+        # Deleting field 'Book._theme_counter'
+        db.delete_column('catalogue_book', '_theme_counter')
+
+        # Deleting field 'Book._short_html_de'
+        db.delete_column('catalogue_book', '_short_html_de')
+
+        # Deleting field 'Book._short_html_fr'
+        db.delete_column('catalogue_book', '_short_html_fr')
+
+        # Deleting field 'Book._short_html_uk'
+        db.delete_column('catalogue_book', '_short_html_uk')
+
+        # Deleting field 'Book._short_html_pl'
+        db.delete_column('catalogue_book', '_short_html_pl')
+
+        # Deleting field 'Book._short_html_lt'
+        db.delete_column('catalogue_book', '_short_html_lt')
+
+        # Deleting field 'Book._short_html_ru'
+        db.delete_column('catalogue_book', '_short_html_ru')
+
+        # Deleting field 'Book._short_html'
+        db.delete_column('catalogue_book', '_short_html')
+
+        # Deleting field 'Book._tag_counter'
+        db.delete_column('catalogue_book', '_tag_counter')
+
+        # Deleting field 'Fragment._short_html_de'
+        db.delete_column('catalogue_fragment', '_short_html_de')
+
+        # Deleting field 'Fragment._short_html_en'
+        db.delete_column('catalogue_fragment', '_short_html_en')
+
+        # Deleting field 'Fragment._short_html_fr'
+        db.delete_column('catalogue_fragment', '_short_html_fr')
+
+        # Deleting field 'Fragment._short_html_es'
+        db.delete_column('catalogue_fragment', '_short_html_es')
+
+        # Deleting field 'Fragment._short_html_uk'
+        db.delete_column('catalogue_fragment', '_short_html_uk')
+
+        # Deleting field 'Fragment._short_html_pl'
+        db.delete_column('catalogue_fragment', '_short_html_pl')
+
+        # Deleting field 'Fragment._short_html_lt'
+        db.delete_column('catalogue_fragment', '_short_html_lt')
+
+        # Deleting field 'Fragment._short_html_ru'
+        db.delete_column('catalogue_fragment', '_short_html_ru')
+
+        # Deleting field 'Fragment._short_html'
+        db.delete_column('catalogue_fragment', '_short_html')
+
+
+    def backwards(self, orm):
+        
+        # Adding field 'Book._short_html_en'
+        db.add_column('catalogue_book', '_short_html_en', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html_es'
+        db.add_column('catalogue_book', '_short_html_es', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._theme_counter'
+        db.add_column('catalogue_book', '_theme_counter', self.gf('catalogue.fields.JSONField')(null=True), keep_default=False)
+
+        # Adding field 'Book._short_html_de'
+        db.add_column('catalogue_book', '_short_html_de', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html_fr'
+        db.add_column('catalogue_book', '_short_html_fr', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html_uk'
+        db.add_column('catalogue_book', '_short_html_uk', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html_pl'
+        db.add_column('catalogue_book', '_short_html_pl', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html_lt'
+        db.add_column('catalogue_book', '_short_html_lt', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html_ru'
+        db.add_column('catalogue_book', '_short_html_ru', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Book._short_html'
+        db.add_column('catalogue_book', '_short_html', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False)
+
+        # Adding field 'Book._tag_counter'
+        db.add_column('catalogue_book', '_tag_counter', self.gf('catalogue.fields.JSONField')(null=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_de'
+        db.add_column('catalogue_fragment', '_short_html_de', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_en'
+        db.add_column('catalogue_fragment', '_short_html_en', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_fr'
+        db.add_column('catalogue_fragment', '_short_html_fr', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_es'
+        db.add_column('catalogue_fragment', '_short_html_es', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_uk'
+        db.add_column('catalogue_fragment', '_short_html_uk', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_pl'
+        db.add_column('catalogue_fragment', '_short_html_pl', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_lt'
+        db.add_column('catalogue_fragment', '_short_html_lt', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html_ru'
+        db.add_column('catalogue_fragment', '_short_html_ru', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'Fragment._short_html'
+        db.add_column('catalogue_fragment', '_short_html', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False)
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'catalogue.book': {
+            'Meta': {'ordering': "('sort_key',)", 'object_name': 'Book'},
+            'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'epub_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
+            'extra_info': ('catalogue.fields.JSONField', [], {'default': "'{}'"}),
+            'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'html_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['catalogue.Book']"}),
+            'parent_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'pdf_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120', 'db_index': 'True'}),
+            'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
+            'txt_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
+            'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'xml_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'})
+        },
+        'catalogue.bookmedia': {
+            'Meta': {'ordering': "('type', 'name')", 'object_name': 'BookMedia'},
+            'book': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'media'", 'to': "orm['catalogue.Book']"}),
+            'extra_info': ('catalogue.fields.JSONField', [], {'default': "'{}'"}),
+            'file': ('catalogue.fields.OverwritingFileField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': "'100'"}),
+            'source_sha1': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': "'100'"}),
+            'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
+        },
+        'catalogue.filerecord': {
+            'Meta': {'ordering': "('-time', '-slug', '-type')", 'object_name': 'FileRecord'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'sha1': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '120', 'db_index': 'True'}),
+            'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'type': ('django.db.models.fields.CharField', [], {'max_length': '20', 'db_index': 'True'})
+        },
+        'catalogue.fragment': {
+            'Meta': {'ordering': "('book', 'anchor')", 'object_name': 'Fragment'},
+            'anchor': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
+            'book': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'fragments'", 'to': "orm['catalogue.Book']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'short_text': ('django.db.models.fields.TextField', [], {}),
+            'text': ('django.db.models.fields.TextField', [], {})
+        },
+        'catalogue.tag': {
+            'Meta': {'ordering': "('sort_key',)", 'unique_together': "(('slug', 'category'),)", 'object_name': 'Tag'},
+            'book_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'main_page': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '120', 'db_index': 'True'}),
+            'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'}),
+            'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'})
+        },
+        'catalogue.tagrelation': {
+            'Meta': {'unique_together': "(('tag', 'content_type', 'object_id'),)", 'object_name': 'TagRelation', 'db_table': "'catalogue_tag_relation'"},
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'items'", 'to': "orm['catalogue.Tag']"})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        }
+    }
+
+    complete_apps = ['catalogue']
index 568679b..bf724fd 100644 (file)
@@ -6,6 +6,7 @@ from datetime import datetime
 
 from django.db import models
 from django.db.models import permalink, Q
 
 from django.db import models
 from django.db.models import permalink, Q
+from django.core.cache import cache
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.models import User
 from django.core.files import File
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.models import User
 from django.core.files import File
@@ -282,7 +283,6 @@ class Book(models.Model):
     description   = models.TextField(_('description'), blank=True)
     created_at    = models.DateTimeField(_('creation date'), auto_now_add=True, db_index=True)
     changed_at    = models.DateTimeField(_('creation date'), auto_now=True, db_index=True)
     description   = models.TextField(_('description'), blank=True)
     created_at    = models.DateTimeField(_('creation date'), auto_now_add=True, db_index=True)
     changed_at    = models.DateTimeField(_('creation date'), auto_now=True, db_index=True)
-    _short_html   = models.TextField(_('short HTML'), editable=False)
     parent_number = models.IntegerField(_('parent number'), default=0)
     extra_info    = JSONField(_('extra information'), default='{}')
     gazeta_link   = models.CharField(blank=True, max_length=240)
     parent_number = models.IntegerField(_('parent number'), default=0)
     extra_info    = JSONField(_('extra information'), default='{}')
     gazeta_link   = models.CharField(blank=True, max_length=240)
@@ -299,9 +299,6 @@ class Book(models.Model):
     tagged   = managers.ModelTaggedItemManager(Tag)
     tags     = managers.TagDescriptor(Tag)
 
     tagged   = managers.ModelTaggedItemManager(Tag)
     tags     = managers.TagDescriptor(Tag)
 
-    _tag_counter = JSONField(null=True, editable=False)
-    _theme_counter = JSONField(null=True, editable=False)
-
     class AlreadyExists(Exception):
         pass
 
     class AlreadyExists(Exception):
         pass
 
@@ -317,13 +314,7 @@ class Book(models.Model):
         self.sort_key = sortify(self.title)
 
         if reset_short_html:
         self.sort_key = sortify(self.title)
 
         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)
+            self.reset_short_html()
 
         return super(Book, self).save(force_insert, force_update)
 
 
         return super(Book, self).save(force_insert, force_update)
 
@@ -405,13 +396,23 @@ class Book(models.Model):
     def get_daisy(self):
         return self.get_media("daisy")                       
 
     def get_daisy(self):
         return self.get_media("daisy")                       
 
+    def reset_short_html(self):
+        cache_key = "Book.short_html/%d/%s"
+        for lang, langname in settings.LANGUAGES:
+            cache.delete(cache_key % (self.id, lang))
+        # Fragment.short_html relies on book's tags, so reset it here too
+        for fragm in self.fragments.all():
+            fragm.reset_short_html()
+
     def short_html(self):
     def short_html(self):
-        key = '_short_html_%s' % get_language()
-        short_html = getattr(self, key)
+        cache_key = "Book.short_html/%d/%s" % (self.id, get_language())
+        short_html = cache.get(cache_key)
 
 
-        if short_html and len(short_html):
+        if short_html is not None:
+            print 'b.s from cache'
             return mark_safe(short_html)
         else:
             return mark_safe(short_html)
         else:
+            print 'b.s manual'
             tags = self.tags.filter(~Q(category__in=('set', 'theme', 'book')))
             tags = [mark_safe(u'<a href="%s">%s</a>' % (tag.get_absolute_url(), tag.name)) for tag in tags]
 
             tags = self.tags.filter(~Q(category__in=('set', 'theme', 'book')))
             tags = [mark_safe(u'<a href="%s">%s</a>' % (tag.get_absolute_url(), tag.name)) for tag in tags]
 
@@ -431,11 +432,10 @@ class Book(models.Model):
 
             formats = [mark_safe(format) for format in formats]
 
 
             formats = [mark_safe(format) for format in formats]
 
-            setattr(self, key, unicode(render_to_string('catalogue/book_short.html',
-                {'book': self, 'tags': tags, 'formats': formats})))
-            self.save(reset_short_html=False)
-            return mark_safe(getattr(self, key))
-
+            short_html = unicode(render_to_string('catalogue/book_short.html',
+                {'book': self, 'tags': tags, 'formats': formats}))
+            cache.set(cache_key, short_html)
+            return mark_safe(short_html)
 
     @property
     def root_ancestor(self):
 
     @property
     def root_ancestor(self):
@@ -648,7 +648,6 @@ class Book(models.Model):
 
         book.title = book_info.title
         book.set_extra_info_value(book_info.to_dict())
 
         book.title = book_info.title
         book.set_extra_info_value(book_info.to_dict())
-        book._short_html = ''
         book.save()
 
         meta_tags = []
         book.save()
 
         meta_tags = []
@@ -710,50 +709,49 @@ class Book(models.Model):
         book.save()
         return book
 
         book.save()
         return book
 
-
-    def refresh_tag_counter(self):
-        tags = {}
-        for child in self.children.all().order_by():
-            for tag_pk, value in child.tag_counter.iteritems():
-                tags[tag_pk] = tags.get(tag_pk, 0) + value
-        for tag in self.tags.exclude(category__in=('book', 'theme', 'set')).order_by():
-            tags[tag.pk] = 1
-        self.set__tag_counter_value(tags)
-        self.save(reset_short_html=False)
-        return tags
-
     def reset_tag_counter(self):
     def reset_tag_counter(self):
-        self._tag_counter = None
-        self.save(reset_short_html=False)
+        cache_key = "Book.tag_counter/%d" % self.id
+        cache.delete(cache_key)
         if self.parent:
             self.parent.reset_tag_counter()
 
     @property
     def tag_counter(self):
         if self.parent:
             self.parent.reset_tag_counter()
 
     @property
     def tag_counter(self):
-        if self._tag_counter is None:
-            return self.refresh_tag_counter()
-        return dict((int(k), v) for k, v in self.get__tag_counter_value().iteritems())
-
-    def refresh_theme_counter(self):
-        tags = {}
-        for fragment in Fragment.tagged.with_any([self.book_tag()]).order_by():
-            for tag in fragment.tags.filter(category='theme').order_by():
-                tags[tag.pk] = tags.get(tag.pk, 0) + 1
-        self.set__theme_counter_value(tags)
-        self.save(reset_short_html=False)
+        cache_key = "Book.tag_counter/%d" % self.id
+        tags = cache.get(cache_key)
+        print 'tag'
+        if tags is None:
+            print 'tag manual'
+            tags = {}
+            for child in self.children.all().order_by():
+                for tag_pk, value in child.tag_counter.iteritems():
+                    tags[tag_pk] = tags.get(tag_pk, 0) + value
+            for tag in self.tags.exclude(category__in=('book', 'theme', 'set')).order_by():
+                tags[tag.pk] = 1
+
+            cache.set(cache_key, tags)
         return tags
 
     def reset_theme_counter(self):
         return tags
 
     def reset_theme_counter(self):
-        self._theme_counter = None
-        self.save(reset_short_html=False)
+        cache_key = "Book.theme_counter/%d" % self.id
+        cache.delete(cache_key)
         if self.parent:
             self.parent.reset_theme_counter()
 
     @property
     def theme_counter(self):
         if self.parent:
             self.parent.reset_theme_counter()
 
     @property
     def theme_counter(self):
-        if self._theme_counter is None:
-            return self.refresh_theme_counter()
-        return dict((int(k), v) for k, v in self.get__theme_counter_value().iteritems())
+        cache_key = "Book.theme_counter/%d" % self.id
+        tags = cache.get(cache_key)
+        print 'theme'
+        if tags is None:
+            print 'theme manual'
+            tags = {}
+            for fragment in Fragment.tagged.with_any([self.book_tag()]).order_by():
+                for tag in fragment.tags.filter(category='theme').order_by():
+                    tags[tag.pk] = tags.get(tag.pk, 0) + 1
+
+            cache.set(cache_key, tags)
+        return tags
 
     def pretty_title(self, html_links=False):
         book = self
 
     def pretty_title(self, html_links=False):
         book = self
@@ -794,7 +792,6 @@ class Book(models.Model):
 class Fragment(models.Model):
     text = models.TextField()
     short_text = models.TextField(editable=False)
 class Fragment(models.Model):
     text = models.TextField()
     short_text = models.TextField(editable=False)
-    _short_html = models.TextField(editable=False)
     anchor = models.CharField(max_length=120)
     book = models.ForeignKey(Book, related_name='fragments')
 
     anchor = models.CharField(max_length=120)
     book = models.ForeignKey(Book, related_name='fragments')
 
@@ -810,16 +807,24 @@ class Fragment(models.Model):
     def get_absolute_url(self):
         return '%s#m%s' % (reverse('book_text', kwargs={'slug': self.book.slug}), self.anchor)
 
     def get_absolute_url(self):
         return '%s#m%s' % (reverse('book_text', kwargs={'slug': self.book.slug}), self.anchor)
 
+    def reset_short_html(self):
+        cache_key = "Fragment.short_html/%d/%s"
+        for lang, langname in settings.LANGUAGES:
+            cache.delete(cache_key % (self.id, lang))
+
     def short_html(self):
     def short_html(self):
-        key = '_short_html_%s' % get_language()
-        short_html = getattr(self, key)
-        if short_html and len(short_html):
+        cache_key = "Fragment.short_html/%d/%s" % (self.id, get_language())
+        short_html = cache.get(cache_key)
+
+        if short_html is not None:
+            print 'f.s from cache'
             return mark_safe(short_html)
         else:
             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))
+            print 'f.s manual'
+            short_html = unicode(render_to_string('catalogue/fragment_short.html',
+                {'fragment': self}))
+            cache.set(cache_key, short_html)
+            return mark_safe(short_html)
 
 
 class FileRecord(models.Model):
 
 
 class FileRecord(models.Model):
index 3b10a96..f9f7ab9 100644 (file)
@@ -5,20 +5,9 @@
 
 from modeltranslation.translator import translator, TranslationOptions
 from infopages.models import InfoPage
 
 from modeltranslation.translator import translator, TranslationOptions
 from infopages.models import InfoPage
-from catalogue.models import Book, Fragment
 
 class InfoPageTranslationOptions(TranslationOptions):
     fields = ('page_title', 'title', 'left_column', 'right_column')
 
 translator.register(InfoPage, InfoPageTranslationOptions)
 
 
 class InfoPageTranslationOptions(TranslationOptions):
     fields = ('page_title', 'title', 'left_column', 'right_column')
 
 translator.register(InfoPage, InfoPageTranslationOptions)
 
-class BookTranslationOptions(TranslationOptions):
-    fields = ('_short_html', )
-
-translator.register(Book, BookTranslationOptions)
-
-class FragmentTranslationOptions(TranslationOptions):
-    fields = ('_short_html', )
-
-translator.register(Fragment, FragmentTranslationOptions)
-