X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/516c726d5bc9a59d8bd672710700e5a753fc8f8e..a3ec7115f15e57fec50c96ccebcd4e6b13e130b6:/apps/catalogue/fields.py diff --git a/apps/catalogue/fields.py b/apps/catalogue/fields.py index fad697f44..0ff2ca9ef 100644 --- a/apps/catalogue/fields.py +++ b/apps/catalogue/fields.py @@ -7,21 +7,25 @@ from django.core.files import File 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 celery.task import Task, task +from celery.utils.log import get_task_logger from waiter.utils import clear_cache +task_logger = get_task_logger(__name__) + class EbookFieldFile(FieldFile): """Represents contents of an ebook file field.""" def build(self): """Build the ebook immediately.""" - return self.field.builder(self) + return self.field.builder.build(self) def build_delay(self): """Builds the ebook in a delayed task.""" - return self.field.builder.delay(self) + return self.field.builder.delay(self.instance, self.field.attname) class EbookField(models.FileField): @@ -32,6 +36,11 @@ class EbookField(models.FileField): super(EbookField, self).__init__(*args, **kwargs) self.format_name = format_name + def deconstruct(self): + name, path, args, kwargs = super(EbookField, self).deconstruct() + args.insert(0, self.format_name) + return name, path, args, kwargs + @property def builder(self): """Finds a celery task suitable for the format of the field.""" @@ -43,7 +52,7 @@ class EbookField(models.FileField): def has(model_instance): return bool(getattr(model_instance, self.attname, None)) has.__doc__ = None - has.__name__ = "has_%s" % self.attname + has.__name__ = str("has_%s" % self.attname) has.short_description = self.name has.boolean = True setattr(cls, 'has_%s' % self.attname, has) @@ -74,7 +83,14 @@ class BuildEbook(Task): """ return getattr(wldoc, "as_%s" % fieldfile.field.format_name)() - def run(self, fieldfile): + def run(self, obj, field_name): + """Just run `build` on FieldFile, can't pass it directly to Celery.""" + task_logger.info("%s -> %s" % (obj.slug, field_name)) + ret = self.build(getattr(obj, field_name)) + obj.flush_includes() + return ret + + def build(self, fieldfile): book = fieldfile.instance out = self.transform(book.wldocument(), fieldfile) fieldfile.save(None, File(open(out.get_filename())), save=False) @@ -101,48 +117,56 @@ class BuildTxt(BuildEbook): class BuildPdf(BuildEbook): @staticmethod def transform(wldoc, fieldfile): - return wldoc.as_pdf(morefloats=settings.LIBRARIAN_PDF_MOREFLOATS) + return wldoc.as_pdf(morefloats=settings.LIBRARIAN_PDF_MOREFLOATS, + cover=True) - def run(self, fieldfile): - BuildEbook.run(self, fieldfile) + def build(self, fieldfile): + BuildEbook.build(self, fieldfile) clear_cache(fieldfile.instance.slug) +@BuildEbook.register('epub') +@task(ignore_result=True) +class BuildEpub(BuildEbook): + @staticmethod + def transform(wldoc, fieldfile): + return wldoc.as_epub(cover=True) + + @BuildEbook.register('html') @task(ignore_result=True) class BuildHtml(BuildEbook): - def run(self, fieldfile): + def build(self, fieldfile): from django.core.files.base import ContentFile - from slughifi import slughifi + from fnpdjango.utils.text.slughifi import slughifi from sortify import sortify from librarian import html from catalogue.models import Fragment, Tag book = fieldfile.instance - meta_tags = list(book.tags.filter( - category__in=('author', 'epoch', 'genre', 'kind'))) - book_tag = book.book_tag() - html_output = self.transform( book.wldocument(parse_dublincore=False), fieldfile) + + # Delete old fragments, create from scratch if necessary. + book.fragments.all().delete() + if html_output: + meta_tags = list(book.tags.filter( + category__in=('author', 'epoch', 'genre', 'kind'))) + + lang = book.language + lang = LANGUAGES_3TO2.get(lang, lang) + if lang not in [ln[0] for ln in settings.LANGUAGES]: + lang = None + fieldfile.save(None, ContentFile(html_output.get_string()), save=False) type(book).objects.filter(pk=book.pk).update(**{ fieldfile.field.attname: fieldfile }) - # get ancestor l-tags for adding to new fragments - ancestor_tags = [] - p = book.parent - while p: - ancestor_tags.append(p.book_tag()) - p = p.parent - - # Delete old fragments and create them from scratch - book.fragments.all().delete() # Extract fragments closed_fragments, open_fragments = html.extract_fragments(fieldfile.path) for fragment in closed_fragments.values(): @@ -154,14 +178,26 @@ class BuildHtml(BuildEbook): for theme_name in theme_names: if not theme_name: continue - tag, created = Tag.objects.get_or_create( - slug=slughifi(theme_name), - category='theme') - if created: - tag.name = theme_name - tag.sort_key = sortify(theme_name.lower()) - tag.save() - themes.append(tag) + if lang == settings.LANGUAGE_CODE: + # Allow creating themes if book in default language. + tag, created = Tag.objects.get_or_create( + slug=slughifi(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.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}) + except Tag.DoesNotExist: + pass + else: + themes.append(tag) if not themes: continue @@ -169,15 +205,24 @@ class BuildHtml(BuildEbook): short_text = truncate_html_words(text, 15) if text == short_text: short_text = '' - new_fragment = Fragment.objects.create(anchor=fragment.id, + 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 + [book_tag] + ancestor_tags) - book.html_built.send(sender=book) + new_fragment.tags = set(meta_tags + themes) + book.html_built.send(sender=type(self), instance=book) return True return False +@BuildEbook.register('cover_thumb') +@task(ignore_result=True) +class BuildCoverThumb(BuildEbook): + @classmethod + def transform(cls, wldoc, fieldfile): + from librarian.cover import WLCover + return WLCover(wldoc.book_info, height=193).output_file() + + class OverwritingFieldFile(FieldFile): """ @@ -196,19 +241,3 @@ class OverwritingFieldFile(FieldFile): class OverwritingFileField(models.FileField): attr_class = OverwritingFieldFile - - -try: - # check for south - from south.modelsinspector import add_introspection_rules -except ImportError: - pass -else: - add_introspection_rules([ - ( - [EbookField], - [], - {'format_name': ('format_name', {})} - ) - ], ["^catalogue\.fields\.EbookField"]) - add_introspection_rules([], ["^catalogue\.fields\.OverwritingFileField"])