Add cover_thumb to tests.
[wolnelektury.git] / src / picture / models.py
index 5bc8d49..643149a 100644 (file)
@@ -10,8 +10,11 @@ from django.conf import settings
 from django.contrib.contenttypes.fields import GenericRelation
 from django.core.files.storage import FileSystemStorage
 from django.utils.datastructures import SortedDict
 from django.contrib.contenttypes.fields import GenericRelation
 from django.core.files.storage import FileSystemStorage
 from django.utils.datastructures import SortedDict
-from fnpdjango.utils.text.slughifi import slughifi
+from slugify import slugify
 from ssify import flush_ssi_includes
 from ssify import flush_ssi_includes
+
+from catalogue.models.tag import prefetched_relations
+from catalogue.utils import split_tags
 from picture import tasks
 from StringIO import StringIO
 import jsonfield
 from picture import tasks
 from StringIO import StringIO
 import jsonfield
@@ -101,7 +104,7 @@ class Picture(models.Model):
         pass
 
     class Meta:
         pass
 
     class Meta:
-        ordering = ('sort_key',)
+        ordering = ('sort_key_author', 'sort_key')
 
         verbose_name = _('picture')
         verbose_name_plural = _('pictures')
 
         verbose_name = _('picture')
         verbose_name_plural = _('pictures')
@@ -112,8 +115,8 @@ class Picture(models.Model):
         self.sort_key = sortify(self.title)[:120]
 
         try:
         self.sort_key = sortify(self.title)[:120]
 
         try:
-            author = self.tags.filter(category='author')[0].sort_key
-        except IndexError:
+            author = self.authors().first().sort_key
+        except AttributeError:
             author = u''
         self.sort_key_author = author
 
             author = u''
         self.sort_key_author = author
 
@@ -124,15 +127,22 @@ class Picture(models.Model):
     def __unicode__(self):
         return self.title
 
     def __unicode__(self):
         return self.title
 
-    def author_str(self):
-        return ", ".join(str(t) for t in self.tags.filter(category='author'))
+    def authors(self):
+        return self.tags.filter(category='author')
 
     def tag_unicode(self, category):
 
     def tag_unicode(self, category):
-        return ", ".join(unicode(t) for t in self.tags.filter(category=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):
         return self.tag_unicode('author')
 
 
     def author_unicode(self):
         return self.tag_unicode('author')
 
+    def tags_by_category(self):
+        return split_tags(self.tags)
+
     @permalink
     def get_absolute_url(self):
         return 'picture.views.picture_detail', [self.slug]
     @permalink
     def get_absolute_url(self):
         return 'picture.views.picture_detail', [self.slug]
@@ -156,7 +166,7 @@ class Picture(models.Model):
             return None
 
     @classmethod
             return None
 
     @classmethod
-    def from_xml_file(cls, xml_file, image_file=None, image_store=None, overwrite=False):
+    def from_xml_file(cls, xml_file, image_file=None, image_store=None, overwrite=False, search_index=True):
         """
         Import xml and it's accompanying image file.
         If image file is missing, it will be fetched by librarian.picture.ImageStore
         """
         Import xml and it's accompanying image file.
         If image file is missing, it will be fetched by librarian.picture.ImageStore
@@ -192,8 +202,10 @@ class Picture(models.Model):
             picture.extra_info = picture_xml.picture_info.to_dict()
 
             picture_tags = set(catalogue.models.Tag.tags_from_info(picture_xml.picture_info))
             picture.extra_info = picture_xml.picture_info.to_dict()
 
             picture_tags = set(catalogue.models.Tag.tags_from_info(picture_xml.picture_info))
-            motif_tags = set()
-            thing_tags = set()
+            for tag in picture_tags:
+                if not tag.for_pictures:
+                    tag.for_pictures = True
+                    tag.save()
 
             area_data = {'themes': {}, 'things': {}}
 
 
             area_data = {'themes': {}, 'things': {}}
 
@@ -207,36 +219,47 @@ class Picture(models.Model):
                 if part.get('object', None) is not None:
                     _tags = set()
                     for objname in part['object'].split(','):
                 if part.get('object', None) is not None:
                     _tags = set()
                     for objname in part['object'].split(','):
-                        objname = objname.strip().capitalize()
+                        objname = objname.strip()
+                        assert objname, 'Empty object name'
+                        # str.capitalize() is wrong, because it also lowers letters
+                        objname = objname[0].upper() + objname[1:]
                         tag, created = catalogue.models.Tag.objects.get_or_create(
                         tag, created = catalogue.models.Tag.objects.get_or_create(
-                            slug=slughifi(objname), category='thing')
+                            slug=slugify(objname), category='thing')
                         if created:
                             tag.name = objname
                             setattr(tag, 'name_%s' % lang, tag.name)
                             tag.sort_key = sortify(tag.name)
                         if created:
                             tag.name = objname
                             setattr(tag, 'name_%s' % lang, tag.name)
                             tag.sort_key = sortify(tag.name)
+                            tag.for_pictures = True
                             tag.save()
                             tag.save()
-                        # thing_tags.add(tag)
                         area_data['things'][tag.slug] = {
                             'object': objname,
                             'coords': part['coords'],
                             }
 
                         _tags.add(tag)
                         area_data['things'][tag.slug] = {
                             'object': objname,
                             'coords': part['coords'],
                             }
 
                         _tags.add(tag)
+                        if not tag.for_pictures:
+                            tag.for_pictures = True
+                            tag.save()
                     area = PictureArea.rectangle(picture, 'thing', part['coords'])
                     area.save()
                     area = PictureArea.rectangle(picture, 'thing', part['coords'])
                     area.save()
+                    # WTF thing area does not inherit tags from picture and theme area does, is it intentional?
                     area.tags = _tags
                 else:
                     _tags = set()
                     for motifs in part['themes']:
                         for motif in motifs.split(','):
                             tag, created = catalogue.models.Tag.objects.get_or_create(
                     area.tags = _tags
                 else:
                     _tags = set()
                     for motifs in part['themes']:
                         for motif in motifs.split(','):
                             tag, created = catalogue.models.Tag.objects.get_or_create(
-                                slug=slughifi(motif), category='theme')
+                                slug=slugify(motif), category='theme')
                             if created:
                                 tag.name = motif
                                 tag.sort_key = sortify(tag.name)
                             if created:
                                 tag.name = motif
                                 tag.sort_key = sortify(tag.name)
+                                tag.for_pictures = True
                                 tag.save()
                             # motif_tags.add(tag)
                             _tags.add(tag)
                                 tag.save()
                             # motif_tags.add(tag)
                             _tags.add(tag)
+                            if not tag.for_pictures:
+                                tag.for_pictures = True
+                                tag.save()
                             area_data['themes'][tag.slug] = {
                                 'theme': motif,
                                 'coords': part['coords']
                             area_data['themes'][tag.slug] = {
                                 'theme': motif,
                                 'coords': part['coords']
@@ -247,7 +270,7 @@ class Picture(models.Model):
                     area.save()
                     area.tags = _tags.union(picture_tags)
 
                     area.save()
                     area.tags = _tags.union(picture_tags)
 
-            picture.tags = picture_tags.union(motif_tags).union(thing_tags)
+            picture.tags = picture_tags
             picture.areas_json = area_data
 
             if image_file is not None:
             picture.areas_json = area_data
 
             if image_file is not None:
@@ -268,6 +291,8 @@ class Picture(models.Model):
             picture.xml_file.save("%s.xml" % picture.slug, File(xml_file))
             picture.save()
             tasks.generate_picture_html(picture.id)
             picture.xml_file.save("%s.xml" % picture.slug, File(xml_file))
             picture.save()
             tasks.generate_picture_html(picture.id)
+            if not settings.NO_SEARCH_INDEX and search_index:
+                tasks.index_picture.delay(picture.id, picture_info=picture_xml.picture_info)
 
         if close_xml_file:
             xml_file.close()
 
         if close_xml_file:
             xml_file.close()
@@ -319,7 +344,7 @@ class Picture(models.Model):
             pics_by_author[tag] = []
 
         for pic in pics.iterator():
             pics_by_author[tag] = []
 
         for pic in pics.iterator():
-            authors = list(pic.tags.filter(category='author'))
+            authors = list(pic.authors().only('pk'))
             if authors:
                 for author in authors:
                     pics_by_author[author].append(pic)
             if authors:
                 for author in authors:
                     pics_by_author[author].append(pic)
@@ -338,9 +363,7 @@ class Picture(models.Model):
         return self._info
 
     def pretty_title(self, html_links=False):
         return self._info
 
     def pretty_title(self, html_links=False):
-        picture = self
-        names = [(tag.name, tag.get_absolute_url())
-                 for tag in self.tags.filter(category='author')]
+        names = [(tag.name, tag.get_absolute_url()) for tag in self.authors().only('name', 'category', 'slug')]
         names.append((self.title, self.get_absolute_url()))
 
         if html_links:
         names.append((self.title, self.get_absolute_url()))
 
         if html_links:
@@ -366,3 +389,17 @@ class Picture(models.Model):
                 ]
             for lang in languages
             ])
                 ]
             for lang in languages
             ])
+
+    def search_index(self, picture_info=None, index=None, index_tags=True, commit=True):
+        if index is None:
+            from search.index import Index
+            index = Index()
+        try:
+            index.index_picture(self, picture_info)
+            if index_tags:
+                index.index_tags()
+            if commit:
+                index.index.commit()
+        except Exception, e:
+            index.index.rollback()
+            raise e