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
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 = (
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)
+
+
+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 = models.get_dynamic_path(None, pdf_name, ext='pdf')
+ return pdf_file
- # 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_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):
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
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
+ else:
+ print "safing %s" % file_name
+ print "to: %s" % DefaultStorage().path(file_name)
+ DefaultStorage().save(file_name, File(open(pdf_file.name)))
finally:
unlink(pdf_file.name)
- # remove zip with all pdf files
+ # remove cached downloadables
remove_zip(settings.ALL_PDF_ZIP)
+ for customized_pdf in get_existing_customized_pdf(self):
+ unlink(customized_pdf)
def build_mobi(self):
""" (Re)builds the MOBI file.