Picture model and importbooks -p to import a picture.
authorMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Wed, 14 Dec 2011 13:10:49 +0000 (14:10 +0100)
committerMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Wed, 14 Dec 2011 13:10:49 +0000 (14:10 +0100)
apps/catalogue/management/commands/importbooks.py
apps/catalogue/models.py
apps/picture/__init__.py [new file with mode: 0644]
apps/picture/models.py [new file with mode: 0644]
wolnelektury/settings.py

index ecd3fcc..699f2c9 100644 (file)
@@ -12,6 +12,7 @@ from django.core.management.color import color_style
 from django.core.files import File
 
 from catalogue.models import Book
+from picture.models import Picture
 
 
 class Command(BaseCommand):
@@ -30,10 +31,44 @@ class Command(BaseCommand):
             help='Don\'t build PDF file'),
         make_option('-w', '--wait-until', dest='wait_until', metavar='TIME',
             help='Wait until specified time (Y-M-D h:m:s)'),
+        make_option('-p', '--picture', action='store_true', dest='import_picture', default=False,
+            help='Import pictures'),
+        
     )
     help = 'Imports books from the specified directories.'
     args = 'directory [directory ...]'
 
+    def import_book(self, file_path, options):
+        verbose = options.get('verbose')
+        file_base, ext = os.path.splitext(file_path)
+        book = Book.from_xml_file(file_path, overwrite=options.get('force'),
+                                  build_epub=options.get('build_epub'),
+                                  build_txt=options.get('build_txt'),
+                                  build_pdf=options.get('build_pdf'),
+                                  build_mobi=options.get('build_mobi'))
+
+        if os.path.isfile(file_base + '.pdf'):
+            book.pdf_file.save('%s.pdf' % book.slug, File(file(file_base + '.pdf')))
+            if verbose:
+                print "Importing %s.pdf" % file_base
+        if os.path.isfile(file_base + '.mobi'):
+            book.mobi_file.save('%s.mobi' % book.slug, File(file(file_base + '.mobi')))
+            if verbose:
+                print "Importing %s.mobi" % file_base
+        if os.path.isfile(file_base + '.epub'):
+            book.epub_file.save('%s.epub' % book.slug, File(file(file_base + '.epub')))
+            if verbose:
+                print "Importing %s.epub" % file_base
+        if os.path.isfile(file_base + '.txt'):
+            book.txt_file.save('%s.txt' % book.slug, File(file(file_base + '.txt')))
+            if verbose:
+                print "Importing %s.txt" % file_base
+        book.save()
+
+    def import_picture(self, file_path, options):
+        picture = Picture.from_xml_file(file_path, overwrite=options.get('force'))
+        return picture
+
     def handle(self, *directories, **options):
         from django.db import transaction
 
@@ -42,13 +77,14 @@ class Command(BaseCommand):
         verbose = options.get('verbose')
         force = options.get('force')
         show_traceback = options.get('traceback', False)
+        import_picture = options.get('import_picture')
 
         wait_until = None
         if options.get('wait_until'):
             wait_until = time.mktime(time.strptime(options.get('wait_until'), '%Y-%m-%d %H:%M:%S'))
             if verbose > 0:
                 print "Will wait until %s; it's %f seconds from now" % (
-                    time.strftime('%Y-%m-%d %H:%M:%S', 
+                    time.strftime('%Y-%m-%d %H:%M:%S',
                     time.localtime(wait_until)), wait_until - time.time())
 
         # Start transaction management.
@@ -83,34 +119,14 @@ class Command(BaseCommand):
 
                     # Import book files
                     try:
-                        book = Book.from_xml_file(file_path, overwrite=force, 
-                                                  build_epub=options.get('build_epub'),
-                                                  build_txt=options.get('build_txt'),
-                                                  build_pdf=options.get('build_pdf'),
-                                                  build_mobi=options.get('build_mobi'))
+                        if import_picture:
+                            self.import_picture(file_path, options)
+                        else:
+                            self.import_book(file_path, options)
                         files_imported += 1
 
-                        if os.path.isfile(file_base + '.pdf'):
-                            book.pdf_file.save('%s.pdf' % book.slug, File(file(file_base + '.pdf')))
-                            if verbose:
-                                print "Importing %s.pdf" % file_base
-                        if os.path.isfile(file_base + '.mobi'):
-                            book.mobi_file.save('%s.mobi' % book.slug, File(file(file_base + '.mobi')))
-                            if verbose:
-                                print "Importing %s.mobi" % file_base
-                        if os.path.isfile(file_base + '.epub'):
-                            book.epub_file.save('%s.epub' % book.slug, File(file(file_base + '.epub')))
-                            if verbose:
-                                print "Importing %s.epub" % file_base
-                        if os.path.isfile(file_base + '.txt'):
-                            book.txt_file.save('%s.txt' % book.slug, File(file(file_base + '.txt')))
-                            if verbose:
-                                print "Importing %s.txt" % file_base
-
-                        book.save()
-
-                    except Book.AlreadyExists, msg:
-                        print self.style.ERROR('%s: Book already imported. Skipping. To overwrite use --force.' %
+                    except (Book.AlreadyExists, Picture.AlreadyExists):
+                        print self.style.ERROR('%s: Book or Picture already imported. Skipping. To overwrite use --force.' %
                             file_path)
                         files_skipped += 1
 
index 12b394d..22cd0ea 100644 (file)
@@ -174,6 +174,31 @@ class Tag(TagBase):
     def url_chunk(self):
         return '/'.join((Tag.categories_dict[self.category], self.slug))
 
+    @staticmethod
+    def tags_from_info(info):
+        from slughifi import slughifi
+        from sortify import sortify
+        meta_tags = []
+        categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch'))
+        for field_name, category in categories:
+            try:
+                tag_names = getattr(info, field_name)
+            except:
+                tag_names = [getattr(info, category)]
+            for tag_name in tag_names:
+                tag_sort_key = tag_name
+                if category == 'author':
+                    tag_sort_key = tag_name.last_name
+                    tag_name = ' '.join(tag_name.first_names) + ' ' + tag_name.last_name
+                tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category)
+                if created:
+                    tag.name = tag_name
+                    tag.sort_key = sortify(tag_sort_key.lower())
+                    tag.save()
+                meta_tags.append(tag)
+        return meta_tags
+
+
 
 def get_dynamic_path(media, filename, ext=None, maxlen=100):
     from slughifi import slughifi
@@ -731,7 +756,6 @@ class Book(models.Model):
     def from_text_and_meta(cls, raw_file, book_info, overwrite=False,
             build_epub=True, build_txt=True, build_pdf=True, build_mobi=True):
         import re
-        from slughifi import slughifi
         from sortify import sortify
 
         # check for parts before we do anything
@@ -766,24 +790,7 @@ class Book(models.Model):
         book.set_extra_info_value(book_info.to_dict())
         book.save()
 
-        meta_tags = []
-        categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch'))
-        for field_name, category in categories:
-            try:
-                tag_names = getattr(book_info, field_name)
-            except:
-                tag_names = [getattr(book_info, category)]
-            for tag_name in tag_names:
-                tag_sort_key = tag_name
-                if category == 'author':
-                    tag_sort_key = tag_name.last_name
-                    tag_name = ' '.join(tag_name.first_names) + ' ' + tag_name.last_name
-                tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category)
-                if created:
-                    tag.name = tag_name
-                    tag.sort_key = sortify(tag_sort_key.lower())
-                    tag.save()
-                meta_tags.append(tag)
+        meta_tags = Tag.tags_from_info(book_info)
 
         book.tags = set(meta_tags + book_shelves)
 
diff --git a/apps/picture/__init__.py b/apps/picture/__init__.py
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/apps/picture/models.py b/apps/picture/models.py
new file mode 100644 (file)
index 0000000..af691f8
--- /dev/null
@@ -0,0 +1,86 @@
+from django.db import models
+import catalogue.models
+from catalogue.fields import OverwritingFileField
+from django.conf import settings
+from django.core.files.storage import FileSystemStorage
+from django.utils.translation import ugettext_lazy as _
+from newtagging import managers
+from os import path
+
+
+picture_storage = FileSystemStorage(location=path.join(settings.MEDIA_ROOT, 'pictures'), base_url=settings.MEDIA_URL + "pictures/")
+
+
+class Picture(models.Model):
+    """
+    Picture resource.
+
+    """
+    title       = models.CharField(_('title'), max_length=120)
+    slug        = models.SlugField(_('slug'), max_length=120, db_index=True, unique=True)
+    sort_key    = models.CharField(_('sort key'), max_length=120, db_index=True, editable=False)
+    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)
+    xml_file    = models.FileField('xml_file', upload_to="xml", storage=picture_storage)
+    image_file  = models.FileField(_('image_file'), upload_to="images", storage=picture_storage)
+    objects     = models.Manager()
+    tagged      = managers.ModelTaggedItemManager(catalogue.models.Tag)
+    tags        = managers.TagDescriptor(catalogue.models.Tag)
+
+    class AlreadyExists(Exception):
+        pass
+
+    class Meta:
+        ordering = ('sort_key',)
+
+        verbose_name = _('picture')
+        verbose_name_plural = _('pictures')
+
+    def save(self, force_insert=False, force_update=False, reset_short_html=True, **kwargs):
+        from sortify import sortify
+
+        self.sort_key = sortify(self.title)
+
+        ret = super(Picture, self).save(force_insert, force_update)
+
+        return ret
+
+    def __unicode__(self):
+        return self.title
+
+    @classmethod
+    def from_xml_file(cls, xml_file, images_path=None, overwrite=False):
+        """
+        Import xml and it's accompanying image file.
+        """
+        from django.core.files import File
+        from librarian.picture import WLPicture
+        close_xml_file = False
+
+        if not isinstance(xml_file, File):
+            xml_file = File(open(xml_file))
+            close_xml_file = True
+        try:
+            # use librarian to parse meta-data
+            picture_xml = WLPicture.from_file(xml_file)
+
+            picture, created = Picture.objects.get_or_create(slug=picture_xml.slug)
+            if not created and not overwrite:
+                raise Picture.AlreadyExists('Picture %s already exists' % picture_xml.slug)
+
+            picture.title = picture_xml.picture_info.title
+
+            picture.tags = catalogue.models.Tag.tags_from_info(picture_xml.picture_info)
+
+            img = picture_xml.image_file()
+            try:
+                picture.image_file.save(path.basename(picture_xml.image_path), File(img))
+            finally:
+                img.close()
+
+            picture.xml_file.save("%s.xml" % picture.slug, File(xml_file))
+            picture.save()
+        finally:
+            if close_xml_file:
+                xml_file.close()
+        return picture
index 5b5d4fe..7ac3cd1 100644 (file)
@@ -151,6 +151,7 @@ INSTALLED_APPS = [
     'sponsors',
     'stats',
     'suggest',
+    'picture',
 ]
 
 #CACHE_BACKEND = 'locmem:///?max_entries=3000'