From c1755a26b0576dab27d4eb72371a5b838d0c3116 Mon Sep 17 00:00:00 2001 From: Marcin Koziej Date: Wed, 14 Dec 2011 14:10:49 +0100 Subject: [PATCH 1/1] Picture model and importbooks -p to import a picture. --- .../management/commands/importbooks.py | 70 +++++++++------ apps/catalogue/models.py | 45 ++++++---- apps/picture/__init__.py | 1 + apps/picture/models.py | 86 +++++++++++++++++++ wolnelektury/settings.py | 1 + 5 files changed, 157 insertions(+), 46 deletions(-) create mode 100644 apps/picture/__init__.py create mode 100644 apps/picture/models.py diff --git a/apps/catalogue/management/commands/importbooks.py b/apps/catalogue/management/commands/importbooks.py index ecd3fcc97..699f2c945 100644 --- a/apps/catalogue/management/commands/importbooks.py +++ b/apps/catalogue/management/commands/importbooks.py @@ -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 diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index 12b394d00..22cd0ea76 100644 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@ -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 index 000000000..8b1378917 --- /dev/null +++ b/apps/picture/__init__.py @@ -0,0 +1 @@ + diff --git a/apps/picture/models.py b/apps/picture/models.py new file mode 100644 index 000000000..af691f8ae --- /dev/null +++ b/apps/picture/models.py @@ -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 diff --git a/wolnelektury/settings.py b/wolnelektury/settings.py index 5b5d4fe0b..7ac3cd1eb 100644 --- a/wolnelektury/settings.py +++ b/wolnelektury/settings.py @@ -151,6 +151,7 @@ INSTALLED_APPS = [ 'sponsors', 'stats', 'suggest', + 'picture', ] #CACHE_BACKEND = 'locmem:///?max_entries=3000' -- 2.20.1