X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/357027375ff8867f42ca34bcbfb5a78b5b185fc3..538526fc82b771cbc149743f129d8b1ae7e3cba2:/src/catalogue/fields.py diff --git a/src/catalogue/fields.py b/src/catalogue/fields.py index 0ff2ca9ef..378377ced 100644 --- a/src/catalogue/fields.py +++ b/src/catalogue/fields.py @@ -4,11 +4,12 @@ # from django.conf import settings from django.core.files import File +from django.core.files.storage import FileSystemStorage from django.db import models from django.db.models.fields.files import FieldFile from catalogue import app_settings from catalogue.constants import LANGUAGES_3TO2 -from catalogue.utils import remove_zip, truncate_html_words +from catalogue.utils import remove_zip, truncate_html_words, gallery_path, gallery_url from celery.task import Task, task from celery.utils.log import get_task_logger from waiter.utils import clear_cache @@ -27,6 +28,14 @@ class EbookFieldFile(FieldFile): """Builds the ebook in a delayed task.""" return self.field.builder.delay(self.instance, self.field.attname) + def get_url(self): + return self.instance.media_url(self.field.attname.split('_')[0]) + + def set_readable(self, readable): + import os + permissions = 0o644 if readable else 0o600 + os.chmod(self.path, permissions) + class EbookField(models.FileField): """Represents an ebook file field, attachable to a model.""" @@ -90,14 +99,22 @@ class BuildEbook(Task): obj.flush_includes() return ret + def set_file_permissions(self, fieldfile): + if fieldfile.instance.preview: + fieldfile.set_readable(False) + def build(self, fieldfile): book = fieldfile.instance out = self.transform(book.wldocument(), fieldfile) fieldfile.save(None, File(open(out.get_filename())), save=False) + self.set_file_permissions(fieldfile) if book.pk is not None: - type(book).objects.filter(pk=book.pk).update(**{ + books = type(book).objects.filter(pk=book.pk) + books.update(**{ fieldfile.field.attname: fieldfile }) + for book in books: + book.save() # just to trigger post-save if fieldfile.field.format_name in app_settings.FORMAT_ZIPS: remove_zip(app_settings.FORMAT_ZIPS[fieldfile.field.format_name]) # Don't decorate BuildEbook, because we want to subclass it. @@ -117,8 +134,8 @@ class BuildTxt(BuildEbook): class BuildPdf(BuildEbook): @staticmethod def transform(wldoc, fieldfile): - return wldoc.as_pdf(morefloats=settings.LIBRARIAN_PDF_MOREFLOATS, - cover=True) + return wldoc.as_pdf(morefloats=settings.LIBRARIAN_PDF_MOREFLOATS, cover=True, + ilustr_path=gallery_path(wldoc.book_info.url.slug)) def build(self, fieldfile): BuildEbook.build(self, fieldfile) @@ -130,7 +147,15 @@ class BuildPdf(BuildEbook): class BuildEpub(BuildEbook): @staticmethod def transform(wldoc, fieldfile): - return wldoc.as_epub(cover=True) + return wldoc.as_epub(cover=True, ilustr_path=gallery_path(wldoc.book_info.url.slug)) + + +@BuildEbook.register('mobi') +@task(ignore_result=True) +class BuildMobi(BuildEbook): + @staticmethod + def transform(wldoc, fieldfile): + return wldoc.as_mobi(cover=True, ilustr_path=gallery_path(wldoc.book_info.url.slug)) @BuildEbook.register('html') @@ -138,16 +163,14 @@ class BuildEpub(BuildEbook): class BuildHtml(BuildEbook): def build(self, fieldfile): from django.core.files.base import ContentFile - from fnpdjango.utils.text.slughifi import slughifi + from slugify import slugify from sortify import sortify from librarian import html from catalogue.models import Fragment, Tag book = fieldfile.instance - html_output = self.transform( - book.wldocument(parse_dublincore=False), - fieldfile) + html_output = self.transform(book.wldocument(parse_dublincore=False), fieldfile) # Delete old fragments, create from scratch if necessary. book.fragments.all().delete() @@ -161,8 +184,8 @@ class BuildHtml(BuildEbook): if lang not in [ln[0] for ln in settings.LANGUAGES]: lang = None - fieldfile.save(None, ContentFile(html_output.get_string()), - save=False) + fieldfile.save(None, ContentFile(html_output.get_string()), save=False) + self.set_file_permissions(fieldfile) type(book).objects.filter(pk=book.pk).update(**{ fieldfile.field.attname: fieldfile }) @@ -181,19 +204,19 @@ class BuildHtml(BuildEbook): if lang == settings.LANGUAGE_CODE: # Allow creating themes if book in default language. tag, created = Tag.objects.get_or_create( - slug=slughifi(theme_name), + slug=slugify(theme_name), category='theme') if created: tag.name = theme_name setattr(tag, "name_%s" % lang, theme_name) tag.sort_key = sortify(theme_name.lower()) + tag.for_books = True tag.save() themes.append(tag) elif lang is not None: # Don't create unknown themes in non-default languages. try: - tag = Tag.objects.get(category='theme', - **{"name_%s" % lang: theme_name}) + tag = Tag.objects.get(category='theme', **{"name_%s" % lang: theme_name}) except Tag.DoesNotExist: pass else: @@ -205,25 +228,63 @@ class BuildHtml(BuildEbook): short_text = truncate_html_words(text, 15) if text == short_text: short_text = '' - new_fragment = Fragment.objects.create(anchor=fragment.id, - book=book, text=text, short_text=short_text) + new_fragment = Fragment.objects.create(anchor=fragment.id, book=book, text=text, short_text=short_text) new_fragment.save() new_fragment.tags = set(meta_tags + themes) + for theme in themes: + if not theme.for_books: + theme.for_books = True + theme.save() book.html_built.send(sender=type(self), instance=book) return True return False + @staticmethod + def transform(wldoc, fieldfile): + # ugly, but we can't use wldoc.book_info here + from librarian import DCNS + url_elem = wldoc.edoc.getroot().find('.//' + DCNS('identifier.url')) + if url_elem is None: + gallery = '' + else: + gallery = gallery_url(slug=url_elem.text.rsplit('/', 1)[1]) + return wldoc.as_html(options={'gallery': "'%s'" % gallery}) + + +class BuildCover(BuildEbook): + def set_file_permissions(self, fieldfile): + pass + + @BuildEbook.register('cover_thumb') @task(ignore_result=True) -class BuildCoverThumb(BuildEbook): +class BuildCoverThumb(BuildCover): @classmethod def transform(cls, wldoc, fieldfile): from librarian.cover import WLCover return WLCover(wldoc.book_info, height=193).output_file() +@BuildEbook.register('cover_api_thumb') +@task(ignore_result=True) +class BuildCoverApiThumb(BuildCover): + @classmethod + def transform(cls, wldoc, fieldfile): + from librarian.cover import WLNoBoxCover + return WLNoBoxCover(wldoc.book_info, height=500).output_file() + +@BuildEbook.register('simple_cover') +@task(ignore_result=True) +class BuildSimpleCover(BuildCover): + @classmethod + def transform(cls, wldoc, fieldfile): + from librarian.cover import WLNoBoxCover + return WLNoBoxCover(wldoc.book_info, height=1000).output_file() + + +# not used, but needed for migrations class OverwritingFieldFile(FieldFile): """ Deletes the old file before saving the new one. @@ -232,12 +293,17 @@ class OverwritingFieldFile(FieldFile): def save(self, name, content, *args, **kwargs): leave = kwargs.pop('leave', None) # delete if there's a file already and there's a new one coming - if not leave and self and (not hasattr(content, 'path') or - content.path != self.path): + if not leave and self and (not hasattr(content, 'path') or content.path != self.path): self.delete(save=False) - return super(OverwritingFieldFile, self).save( - name, content, *args, **kwargs) + return super(OverwritingFieldFile, self).save(name, content, *args, **kwargs) class OverwritingFileField(models.FileField): attr_class = OverwritingFieldFile + + +class OverwriteStorage(FileSystemStorage): + + def get_available_name(self, name, max_length=None): + self.delete(name) + return name