X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/22af332597f857ee4fe60ea2ebfd8723fd9d5da9..e2df026c95a4f2751d7355d3e43676dcc0ad7512:/apps/catalogue/models.py diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index 22ed32510..f8d5f1b08 100644 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@ -8,6 +8,7 @@ from django.db import models from django.db.models import permalink, Q import django.dispatch from django.core.cache import cache +from django.core.files.storage import DefaultStorage from django.utils.translation import ugettext_lazy as _ from django.contrib.auth.models import User from django.template.loader import render_to_string @@ -23,6 +24,10 @@ from newtagging.models import TagBase, tags_updated from newtagging import managers from catalogue.fields import JSONField, OverwritingFileField from catalogue.utils import create_zip +from shutil import copy +from glob import glob +import re +from os import path TAG_CATEGORIES = ( @@ -170,23 +175,46 @@ class Tag(TagBase): return '/'.join((Tag.categories_dict[self.category], self.slug)) +def get_dynamic_path(media, filename, ext=None, maxlen=100): + from slughifi import slughifi + + # how to put related book's slug here? + if not ext: + if media.type == 'daisy': + ext = 'daisy.zip' + else: + ext = media.type + if media is None or not media.name: + name = slughifi(filename.split(".")[0]) + else: + name = slughifi(media.name) + return 'book/%s/%s.%s' % (ext, name[:maxlen-len('book/%s/.%s' % (ext, ext))-4], ext) + + # TODO: why is this hard-coded ? def book_upload_path(ext=None, maxlen=100): - def get_dynamic_path(media, filename, ext=ext): - from slughifi import slughifi + return lambda *args: get_dynamic_path(*args, ext=ext, maxlen=maxlen) - # how to put related book's slug here? - if not ext: - if media.type == 'daisy': - ext = 'daisy.zip' - else: - ext = media.type - if not media.name: - name = slughifi(filename.split(".")[0]) - else: - name = slughifi(media.name) - return 'book/%s/%s.%s' % (ext, name[:maxlen-len('book/%s/.%s' % (ext, ext))-4], ext) - return get_dynamic_path + +def get_customized_pdf_path(book, customizations): + """ + Returns a MEDIA_ROOT relative path for a customized pdf. The name will contain a hash of customization options. + """ + customizations.sort() + h = hash(tuple(customizations)) + pdf_name = '%s-custom-%s' % (book.slug, h) + pdf_file = get_dynamic_path(None, pdf_name, ext='pdf') + return pdf_file + + +def get_existing_customized_pdf(book): + """ + Returns a list of paths to generated customized pdf of a book + """ + pdf_glob = '%s-custom-' % (book.slug,) + pdf_glob = get_dynamic_path(None, pdf_glob, ext='pdf') + pdf_glob = re.sub(r"[.]([a-z0-9]+)$", "*.\\1", pdf_glob) + return glob(path.join(settings.MEDIA_ROOT, pdf_glob)) class BookMedia(models.Model): @@ -465,9 +493,10 @@ class Book(models.Model): has_daisy_file.short_description = 'DAISY' has_daisy_file.boolean = True - def build_pdf(self): + def build_pdf(self, customizations=None, file_name=None): """ (Re)builds the pdf file. - + customizations - customizations which are passed to LaTeX class file. + file_name - save the pdf file under a different name and DO NOT save it in db. """ from tempfile import NamedTemporaryFile from os import unlink @@ -480,15 +509,31 @@ class Book(models.Model): pdf.transform(ORMDocProvider(self), file_path=str(self.xml_file.path), output_file=pdf_file, + customizations=customizations ) - self.pdf_file.save('%s.pdf' % self.slug, File(open(pdf_file.name))) + if file_name is None: + # we'd like to be sure not to overwrite changes happening while + # (timely) pdf generation is taking place (async celery scenario) + current_self = Book.objects.get(id=self.id) + current_self.pdf_file.save('%s.pdf' % self.slug, File(open(pdf_file.name))) + self.pdf_file = current_self.pdf_file + + # remove cached downloadables + remove_zip(settings.ALL_PDF_ZIP) + + for customized_pdf in get_existing_customized_pdf(self): + unlink(customized_pdf) + else: + print "save %s to: %s" % (file_name, DefaultStorage().path(file_name)) + + pdf_django_file = File(open(pdf_file.name)) + DefaultStorage().save(file_name, pdf_django_file) + pdf_django_file.close() finally: + pass unlink(pdf_file.name) - # remove zip with all pdf files - remove_zip(settings.ALL_PDF_ZIP) - def build_mobi(self): """ (Re)builds the MOBI file. @@ -885,6 +930,19 @@ class Book(models.Model): return books_by_author, orphans, books_by_parent + _audiences_pl = { + "SP1": (1, u"szkoła podstawowa"), + "SP2": (1, u"szkoła podstawowa"), + "P": (1, u"szkoła podstawowa"), + "G": (2, u"gimnazjum"), + "L": (3, u"liceum"), + "LP": (3, u"liceum"), + } + def audiences_pl(self): + audiences = self.get_extra_info_value().get('audiences', []) + audiences = sorted(set([self._audiences_pl[a] for a in audiences])) + return [a[1] for a in audiences] + def _has_factory(ftype): has = lambda self: bool(getattr(self, "%s_file" % ftype))