From 142cf364fb3fc7cd95df709126ada97b6944c128 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 16 Dec 2011 16:36:38 +0100 Subject: [PATCH] cleaning around ebooks --- apps/api/handlers.py | 11 +-- apps/catalogue/forms.py | 14 +-- .../management/commands/importbooks.py | 23 ++--- apps/catalogue/management/commands/pack.py | 4 +- apps/catalogue/models.py | 99 ++++++------------- apps/catalogue/views.py | 44 +++------ wolnelektury/settings.py | 34 +++---- .../templates/catalogue/book_detail.html | 7 +- 8 files changed, 79 insertions(+), 157 deletions(-) diff --git a/apps/api/handlers.py b/apps/api/handlers.py index f83a49219..e10a4b5a2 100644 --- a/apps/api/handlers.py +++ b/apps/api/handlers.py @@ -93,7 +93,7 @@ class BookDetailHandler(BaseHandler): """ allowed_methods = ['GET'] - fields = ['title', 'parent'] + Book.file_types + [ + fields = ['title', 'parent'] + Book.formats + [ 'media', 'url'] + category_singular.keys() @piwik_track @@ -205,7 +205,7 @@ def _file_getter(format): else: return '' return get_file -for format in Book.file_types: +for format in Book.formats: setattr(BooksHandler, format, _file_getter(format)) @@ -364,8 +364,7 @@ class CatalogueHandler(BaseHandler): def book_dict(book, fields=None): all_fields = ['url', 'title', 'description', 'gazeta_link', 'wiki_link', - ] + Book.file_types + [ - 'mp3', 'ogg', 'daisy', + ] + Book.formats + BookMedia.formats + [ 'parent', 'parent_number', 'tags', 'license', 'license_description', 'source_name', @@ -382,7 +381,7 @@ class CatalogueHandler(BaseHandler): obj = {} for field in fields: - if field in Book.file_types: + if field in Book.formats: f = getattr(book, field+'_file') if f: obj[field] = { @@ -390,7 +389,7 @@ class CatalogueHandler(BaseHandler): 'size': f.size, } - elif field in ('mp3', 'ogg', 'daisy'): + elif field in BookMedia.formats: media = [] for m in book.media.filter(type=field): media.append({ diff --git a/apps/catalogue/forms.py b/apps/catalogue/forms.py index 094aaaf23..852513a57 100644 --- a/apps/catalogue/forms.py +++ b/apps/catalogue/forms.py @@ -78,20 +78,12 @@ class NewSetForm(forms.Form): return new_set -FORMATS = ( - ('mp3', 'MP3'), - ('ogg', 'OGG'), - ('pdf', 'PDF'), - ('odt', 'ODT'), - ('txt', 'TXT'), - ('epub', 'EPUB'), - ('daisy', 'DAISY'), - ('mobi', 'MOBI'), -) +FORMATS = [(f, f.upper()) for f in Book.ebook_formats] class DownloadFormatsForm(forms.Form): - formats = forms.MultipleChoiceField(required=False, choices=FORMATS, widget=forms.CheckboxSelectMultiple) + formats = forms.MultipleChoiceField(required=False, choices=FORMATS, + widget=forms.CheckboxSelectMultiple) def __init__(self, *args, **kwargs): super(DownloadFormatsForm, self).__init__(*args, **kwargs) diff --git a/apps/catalogue/management/commands/importbooks.py b/apps/catalogue/management/commands/importbooks.py index ecd3fcc97..24356cc2d 100644 --- a/apps/catalogue/management/commands/importbooks.py +++ b/apps/catalogue/management/commands/importbooks.py @@ -90,22 +90,13 @@ class Command(BaseCommand): build_mobi=options.get('build_mobi')) 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 + for ebook_format in Book.ebook_formats: + if os.path.isfile(file_base + '.' + ebook_format): + getattr(book, '%s_file' % ebook_format).save( + '%s.%s' % (book.slug, ebook_format), + File(file(file_base + '.' + ebook_format))) + if verbose: + print "Importing %s.%s" % (file_base, ebook_format) book.save() diff --git a/apps/catalogue/management/commands/pack.py b/apps/catalogue/management/commands/pack.py index c75f092a9..280c0f6ad 100755 --- a/apps/catalogue/management/commands/pack.py +++ b/apps/catalogue/management/commands/pack.py @@ -23,7 +23,7 @@ class Command(BaseCommand): make_option('-e', '--exclude', dest='exclude', metavar='SLUG,...', help='Exclude specific books by slug') ) - help = 'Prepare data for Lesmianator.' + help = 'Prepare ZIP package with files of given type.' args = '[%s] output_path.zip' % '|'.join(ftypes) def handle(self, ftype, path, **options): @@ -33,7 +33,7 @@ class Command(BaseCommand): include = options.get('include') exclude = options.get('exclude') - if ftype in Book.file_types: + if ftype in Book.formats: field = "%s_file" % ftype else: print self.style.ERROR('Unknown file type.') diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index a5b0ebf0c..3fd80ef8a 100644 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@ -2,6 +2,7 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +from collections import namedtuple from datetime import datetime from django.db import models @@ -40,13 +41,6 @@ TAG_CATEGORIES = ( ('book', _('book')), ) -MEDIA_FORMATS = ( - ('odt', _('ODT file')), - ('mp3', _('MP3 file')), - ('ogg', _('OGG file')), - ('daisy', _('DAISY file')), -) - # not quite, but Django wants you to set a timeout CACHE_FOREVER = 2419200 # 28 days @@ -180,10 +174,8 @@ def get_dynamic_path(media, filename, ext=None, maxlen=100): # how to put related book's slug here? if not ext: - if media.type == 'daisy': - ext = 'daisy.zip' - else: - ext = media.type + # BookMedia case + ext = media.formats[media.type].ext if media is None or not media.name: name = slughifi(filename.split(".")[0]) else: @@ -220,7 +212,16 @@ def get_existing_customized_pdf(book): class BookMedia(models.Model): - type = models.CharField(_('type'), choices=MEDIA_FORMATS, max_length="100") + FileFormat = namedtuple("FileFormat", "name ext") + formats = SortedDict([ + ('mp3', FileFormat(name='MP3', ext='mp3')), + ('ogg', FileFormat(name='Ogg Vorbis', ext='ogg')), + ('daisy', FileFormat(name='DAISY', ext='daisy.zip')), + ]) + format_choices = [(k, _('%s file') % t.name) + for k, t in formats.items()] + + type = models.CharField(_('type'), choices=format_choices, max_length="100") name = models.CharField(_('name'), max_length="100") file = OverwritingFileField(_('file'), upload_to=book_upload_path()) uploaded_at = models.DateTimeField(_('creation date'), auto_now_add=True, editable=False) @@ -333,8 +334,9 @@ class Book(models.Model): wiki_link = models.CharField(blank=True, max_length=240) # files generated during publication - file_types = ['epub', 'html', 'mobi', 'pdf', 'txt', 'xml'] - + ebook_formats = ['pdf', 'epub', 'mobi', 'txt'] + formats = ebook_formats + ['html', 'xml'] + parent = models.ForeignKey('self', blank=True, null=True, related_name='children') objects = models.Manager() tagged = managers.ModelTaggedItemManager(Tag) @@ -431,14 +433,14 @@ class Book(models.Model): return book_tag def has_media(self, type): - if type in Book.file_types: + if type in Book.formats: return bool(getattr(self, "%s_file" % type)) else: return self.media.filter(type=type).exists() def get_media(self, type): if self.has_media(type): - if type in Book.file_types: + if type in Book.formats: return getattr(self, "%s_file" % type) else: return self.media.filter(type=type) @@ -482,14 +484,12 @@ class Book(models.Model): # files generated during publication if self.has_media("html"): formats.append(u'%s' % (reverse('book_text', args=[self.fileid()]), _('Read online'))) - if self.has_media("pdf"): - formats.append(u'PDF' % self.get_media('pdf').url) - if self.has_media("mobi"): - formats.append(u'MOBI' % self.get_media('mobi').url) - if self.root_ancestor.has_media("epub"): - formats.append(u'EPUB' % self.root_ancestor.get_media('epub').url) - if self.has_media("txt"): - formats.append(u'TXT' % self.get_media('txt').url) + for ebook_format in self.ebook_formats: + if self.has_media(ebook_format): + formats.append(u'%s' % ( + self.get_media(ebook_format).url, + ebook_format.upper() + )) # other files for m in self.media.order_by('type'): formats.append(u'%s' % (m.file.url, m.type.upper())) @@ -520,29 +520,12 @@ class Book(models.Model): cache.set(cache_key, short_html, CACHE_FOREVER) return mark_safe(short_html) - @property - def root_ancestor(self): - """ returns the oldest ancestor """ - - if not hasattr(self, '_root_ancestor'): - book = self - while book.parent: - book = book.parent - self._root_ancestor = book - return self._root_ancestor - - def has_description(self): return len(self.description) > 0 has_description.short_description = _('description') has_description.boolean = True # ugly ugly ugly - def has_odt_file(self): - return bool(self.has_media("odt")) - has_odt_file.short_description = 'ODT' - has_odt_file.boolean = True - def has_mp3_file(self): return bool(self.has_media("mp3")) has_mp3_file.short_description = 'MP3' @@ -609,34 +592,15 @@ class Book(models.Model): # remove zip with all mobi files remove_zip(settings.ALL_MOBI_ZIP) - def build_epub(self, remove_descendants=True): - """ (Re)builds the epub file. - If book has a parent, does nothing. - Unless remove_descendants is False, descendants' epubs are removed. - """ + def build_epub(self): + """(Re)builds the epub file.""" from django.core.files import File from catalogue.utils import remove_zip - if self.parent: - # don't need an epub - return - epub = self.wldocument().as_epub() - try: - epub.transform(ORMDocProvider(self), self.fileid(), output_file=epub_file) - self.epub_file.save('%s.epub' % self.fileid(), File(open(epub.get_filename()))) - except NoDublinCore: - pass - - book_descendants = list(self.children.all()) - while len(book_descendants) > 0: - child_book = book_descendants.pop(0) - if remove_descendants and child_book.has_epub_file(): - child_book.epub_file.delete() - # save anyway, to refresh short_html - child_book.save() - book_descendants += list(child_book.children.all()) + self.epub_file.save('%s.epub' % self.fileid(), + File(open(epub.get_filename()))) # remove zip package with all epub files remove_zip(settings.ALL_EPUB_ZIP) @@ -822,17 +786,16 @@ class Book(models.Model): book.build_txt() if not settings.NO_BUILD_EPUB and build_epub: - book.root_ancestor.build_epub() + book.build_epub() if not settings.NO_BUILD_PDF and build_pdf: - book.root_ancestor.build_pdf() + book.build_pdf() if not settings.NO_BUILD_MOBI and build_mobi: book.build_mobi() book_descendants = list(book.children.all()) # add l-tag to descendants and their fragments - # delete unnecessary EPUB files while len(book_descendants) > 0: child_book = book_descendants.pop(0) child_book.tags = list(child_book.tags) + [book_tag] @@ -1002,7 +965,7 @@ def _has_factory(ftype): # add the file fields -for t in Book.file_types: +for t in Book.formats: field_name = "%s_file" % t models.FileField(_("%s file" % t.upper()), upload_to=book_upload_path(t), diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 3a0e04ad7..e6e5eb927 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -593,32 +593,18 @@ def download_shelf(request, slug): if form.is_valid(): formats = form.cleaned_data['formats'] if len(formats) == 0: - formats = ['pdf', 'epub', 'mobi', 'odt', 'txt'] + formats = models.Book.ebook_formats # Create a ZIP archive temp = tempfile.TemporaryFile() archive = zipfile.ZipFile(temp, 'w') - already = set() for book in collect_books(models.Book.tagged.with_all(shelf)): fileid = book.fileid() - if 'pdf' in formats and book.pdf_file: - filename = book.pdf_file.path - archive.write(filename, str('%s.pdf' % fileid)) - if 'mobi' in formats and book.mobi_file: - filename = book.mobi_file.path - archive.write(filename, str('%s.mobi' % fileid)) - if book.root_ancestor not in already and 'epub' in formats and book.root_ancestor.epub_file: - filename = book.root_ancestor.epub_file.path - archive.write(filename, str('%s.epub' % book.root_ancestor.fileid())) - already.add(book.root_ancestor) - if 'odt' in formats and book.has_media("odt"): - for file in book.get_media("odt"): - filename = file.file.path - archive.write(filename, str('%s.odt' % slughifi(file.name))) - if 'txt' in formats and book.txt_file: - filename = book.txt_file.path - archive.write(filename, str('%s.txt' % fileid)) + for ebook_format in models.Book.ebook_formats: + if ebook_format in formats and book.has_media(ebook_format): + filename = book.get_media(ebook_format).path + archive.write(filename, str('%s.%s' % (fileid, ebook_format))) archive.close() response = HttpResponse(content_type='application/zip', mimetype='application/x-zip-compressed') @@ -637,20 +623,14 @@ def shelf_book_formats(request, shelf): """ shelf = get_object_or_404(models.Tag, slug=shelf, category='set') - formats = {'pdf': False, 'epub': False, 'mobi': False, 'odt': False, 'txt': False} + formats = {} + for ebook_format in models.Book.ebook_formats: + formats[ebook_format] = False for book in collect_books(models.Book.tagged.with_all(shelf)): - if book.pdf_file: - formats['pdf'] = True - if book.root_ancestor.epub_file: - formats['epub'] = True - if book.mobi_file: - formats['mobi'] = True - if book.txt_file: - formats['txt'] = True - for format in ('odt',): - if book.has_media(format): - formats[format] = True + for ebook_format in models.Book.ebook_formats: + if book.has_media(ebook_format): + formats[ebook_format] = True return HttpResponse(LazyEncoder().encode(formats)) @@ -774,7 +754,7 @@ def download_zip(request, format, book=None): kwargs = models.Book.split_fileid(book) url = None - if format in ('pdf', 'epub', 'mobi'): + if format in models.Book.ebook_formats: url = models.Book.zip_format(format) elif format == 'audiobook' and kwargs is not None: book = get_object_or_404(models.Book, **kwargs) diff --git a/wolnelektury/settings.py b/wolnelektury/settings.py index ed63a1dbb..bd4e8a0b4 100644 --- a/wolnelektury/settings.py +++ b/wolnelektury/settings.py @@ -180,12 +180,12 @@ COMPRESS_CSS = { } COMPRESS_JS = { - 'jquery': { - #'source_filenames': ('js/jquery.js',), - 'source_filenames': [], - 'output_filename': 'js/jquery.min.js', - }, - 'all': { + #~ 'jquery': { + #~ #'source_filenames': ('js/jquery.js',), + #~ 'source_filenames': [], + #~ 'output_filename': 'js/jquery.min.js', + #~ }, + #~ 'all': { #~ 'source_filenames': ('js/jquery.autocomplete.js', 'js/jquery.form.js', #~ 'js/jquery.countdown.js', 'js/jquery.countdown-pl.js', #~ 'js/jquery.countdown-de.js', 'js/jquery.countdown-uk.js', @@ -194,19 +194,19 @@ COMPRESS_JS = { #~ 'js/jquery.cycle.min.js', #~ 'js/jquery.jqmodal.js', 'js/jquery.labelify.js', 'js/catalogue.js', #~ ), - 'source_filenames': [], - 'output_filename': 'js/all?.min.js', - }, - 'book': { + #~ 'source_filenames': [], + #~ 'output_filename': 'js/all?.min.js', + #~ }, + #~ 'book': { #~ 'source_filenames': ('js/jquery.eventdelegation.js', 'js/jquery.scrollto.js', 'js/jquery.highlightfade.js', 'js/book.js',), - 'source_filenames': [], - 'output_filename': 'js/book?.min.js', - }, - 'book_ie': { + #~ 'source_filenames': [], + #~ 'output_filename': 'js/book?.min.js', + #~ }, + #~ 'book_ie': { #~ 'source_filenames': ('js/ierange-m2.js',), - 'source_filenames': [], - 'output_filename': 'js/book_ie?.min.js', - } + #~ 'source_filenames': [], + #~ 'output_filename': 'js/book_ie?.min.js', + #~ } } diff --git a/wolnelektury/templates/catalogue/book_detail.html b/wolnelektury/templates/catalogue/book_detail.html index 2d83c733b..c47e2176d 100644 --- a/wolnelektury/templates/catalogue/book_detail.html +++ b/wolnelektury/templates/catalogue/book_detail.html @@ -49,8 +49,8 @@ {% if book.pdf_file %} {% trans {% endif %} - {% if book.root_ancestor.epub_file %} - {% trans + {% if book.epub_file %} + {% trans {% endif %} {% if book.mobi_file %} {% trans @@ -58,9 +58,6 @@ {% if book.txt_file %} {% trans {% endif %} - {% for media in book.get_odt %} - {% trans - {% endfor %} {% if book.pdf_file %}
{% trans "Dowload customized PDF" %}. -- 2.20.1