locale
[redakcja.git] / apps / catalogue / models / book.py
index 2a0d552..90327b2 100755 (executable)
@@ -8,14 +8,10 @@ from django.db import models, transaction
 from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
 from slughifi import slughifi
 from django.template.loader import render_to_string
 from django.utils.translation import ugettext_lazy as _
 from slughifi import slughifi
-from librarian import NoDublinCore, ParseError, ValidationError
-from librarian.dcparser import BookInfo
 
 
-import apiclient
 from catalogue.helpers import cached_in_field
 from catalogue.models import BookPublishRecord, ChunkPublishRecord
 from catalogue.helpers import cached_in_field
 from catalogue.models import BookPublishRecord, ChunkPublishRecord
-from catalogue.signals import post_publish
-from catalogue.tasks import refresh_instance
+from catalogue.tasks import refresh_instance, book_content_updated
 from catalogue.xml_tools import compile_text, split_xml
 
 
 from catalogue.xml_tools import compile_text, split_xml
 
 
@@ -36,6 +32,8 @@ class Book(models.Model):
     _single = models.NullBooleanField(editable=False, db_index=True)
     _new_publishable = models.NullBooleanField(editable=False)
     _published = models.NullBooleanField(editable=False)
     _single = models.NullBooleanField(editable=False, db_index=True)
     _new_publishable = models.NullBooleanField(editable=False)
     _published = models.NullBooleanField(editable=False)
+    dc_slug = models.CharField(max_length=128, null=True, blank=True,
+            editable=False, db_index=True)
 
     class NoTextError(BaseException):
         pass
 
     class NoTextError(BaseException):
         pass
@@ -72,6 +70,11 @@ class Book(models.Model):
     def get_absolute_url(self):
         return ("catalogue_book", [self.slug])
 
     def get_absolute_url(self):
         return ("catalogue_book", [self.slug])
 
+    def correct_about(self):
+        return "http://%s%s" % (
+            Site.objects.get_current().domain,
+            self.get_absolute_url()
+        )
 
     # Creating & manipulating
     # =======================
 
     # Creating & manipulating
     # =======================
@@ -198,7 +201,7 @@ class Book(models.Model):
             chunk.commit('')
 
         for i in range(len(other)):
             chunk.commit('')
 
         for i in range(len(other)):
-            self[i].prepend_history(other[i])
+            self[i].prepend_history(other[0])
 
         assert not other.chunk_set.exists()
         other.delete()
 
         assert not other.chunk_set.exists()
         other.delete()
@@ -221,6 +224,9 @@ class Book(models.Model):
             raise AssertionError(_('Not all chunks have publishable revisions.'))
         book_xml = self.materialize(changes=changes)
 
             raise AssertionError(_('Not all chunks have publishable revisions.'))
         book_xml = self.materialize(changes=changes)
 
+        from librarian.dcparser import BookInfo
+        from librarian import NoDublinCore, ParseError, ValidationError
+
         try:
             bi = BookInfo.from_string(book_xml.encode('utf-8'))
         except ParseError, e:
         try:
             bi = BookInfo.from_string(book_xml.encode('utf-8'))
         except ParseError, e:
@@ -230,7 +236,7 @@ class Book(models.Model):
         except ValidationError, e:
             raise AssertionError(_('Invalid Dublin Core') + ': ' + str(e))
 
         except ValidationError, e:
             raise AssertionError(_('Invalid Dublin Core') + ': ' + str(e))
 
-        valid_about = "http://%s%s" % (Site.objects.get_current().domain, self.get_absolute_url())
+        valid_about = self.correct_about()
         assert bi.about == valid_about, _("rdf:about is not") + " " + valid_about
 
     def hidden(self):
         assert bi.about == valid_about, _("rdf:about is not") + " " + valid_about
 
     def hidden(self):
@@ -267,7 +273,33 @@ class Book(models.Model):
     def short_html(self):
         return render_to_string('catalogue/book_list/book.html', {'book': self})
 
     def short_html(self):
         return render_to_string('catalogue/book_list/book.html', {'book': self})
 
+    def book_info(self, publishable=True):
+        try:
+            book_xml = self.materialize(publishable=publishable)
+        except self.NoTextError:
+            pass
+        else:
+            from librarian.dcparser import BookInfo
+            from librarian import NoDublinCore, ParseError, ValidationError
+            try:
+                return BookInfo.from_string(book_xml.encode('utf-8'))
+            except (self.NoTextError, ParseError, NoDublinCore, ValidationError):
+                return None
+
+    def refresh_dc_cache(self):
+        update = {
+            'dc_slug': None,
+        }
+
+        info = self.book_info()
+        if info is not None:
+            update['dc_slug'] = info.slug
+        Book.objects.filter(pk=self.pk).update(**update)
+
     def touch(self):
     def touch(self):
+        # this should only really be done when text or publishable status changes
+        book_content_updated.delay(self)
+
         update = {
             "_new_publishable": self.is_new_publishable(),
             "_published": self.is_published(),
         update = {
             "_new_publishable": self.is_new_publishable(),
             "_published": self.is_published(),
@@ -316,6 +348,9 @@ class Book(models.Model):
         """
             Publishes a book on behalf of a (local) user.
         """
         """
             Publishes a book on behalf of a (local) user.
         """
+        import apiclient
+        from catalogue.signals import post_publish
+
         self.assert_publishable()
         changes = self.get_current_changes(publishable=True)
         book_xml = self.materialize(changes=changes)
         self.assert_publishable()
         changes = self.get_current_changes(publishable=True)
         book_xml = self.materialize(changes=changes)