From: Radek Czajka Date: Fri, 16 Dec 2011 16:13:21 +0000 (+0100) Subject: Merge branch 'picture' into pretty X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/f906193db2ec44590f57beae2e8ee2df76117b7b?ds=sidebyside;hp=-c Merge branch 'picture' into pretty Conflicts: apps/catalogue/management/commands/importbooks.py --- f906193db2ec44590f57beae2e8ee2df76117b7b diff --combined apps/catalogue/management/commands/importbooks.py index 24356cc2d,699f2c945..d097ddd1a --- a/apps/catalogue/management/commands/importbooks.py +++ b/apps/catalogue/management/commands/importbooks.py @@@ -12,6 -12,7 +12,7 @@@ from django.core.management.color impor from django.core.files import File from catalogue.models import Book + from picture.models import Picture class Command(BaseCommand): @@@ -30,10 -31,44 +31,36 @@@ help='Don\'t build PDF file'), make_option('-w', '--wait-until', dest='wait_until', metavar='TIME', help='Wait until specified time (Y-M-D h:m:s)'), + make_option('-p', '--picture', action='store_true', dest='import_picture', default=False, + help='Import pictures'), + ) help = 'Imports books from the specified directories.' args = 'directory [directory ...]' + def import_book(self, file_path, options): + verbose = options.get('verbose') + file_base, ext = os.path.splitext(file_path) + book = Book.from_xml_file(file_path, overwrite=options.get('force'), + build_epub=options.get('build_epub'), + build_txt=options.get('build_txt'), + build_pdf=options.get('build_pdf'), + build_mobi=options.get('build_mobi')) ++ fileid = book.fileid() ++ for ebook_format in Book.ebook_formats: ++ if os.path.isfile(file_base + '.' + ebook_format): ++ getattr(book, '%s_file' % ebook_format).save( ++ '%s.%s' % (fileid, ebook_format), ++ File(file(file_base + '.' + ebook_format))) ++ if verbose: ++ print "Importing %s.%s" % (file_base, ebook_format) + - 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 + book.save() + + def import_picture(self, file_path, options): + picture = Picture.from_xml_file(file_path, overwrite=options.get('force')) + return picture + def handle(self, *directories, **options): from django.db import transaction @@@ -42,13 -77,14 +69,14 @@@ verbose = options.get('verbose') force = options.get('force') show_traceback = options.get('traceback', False) + import_picture = options.get('import_picture') wait_until = None if options.get('wait_until'): wait_until = time.mktime(time.strptime(options.get('wait_until'), '%Y-%m-%d %H:%M:%S')) if verbose > 0: print "Will wait until %s; it's %f seconds from now" % ( - time.strftime('%Y-%m-%d %H:%M:%S', + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(wait_until)), wait_until - time.time()) # Start transaction management. @@@ -83,25 -119,14 +111,14 @@@ # Import book files try: - book = Book.from_xml_file(file_path, overwrite=force, - build_epub=options.get('build_epub'), - build_txt=options.get('build_txt'), - build_pdf=options.get('build_pdf'), - build_mobi=options.get('build_mobi')) + if import_picture: + self.import_picture(file_path, options) + else: + self.import_book(file_path, options) files_imported += 1 - 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() - - except Book.AlreadyExists, msg: - print self.style.ERROR('%s: Book already imported. Skipping. To overwrite use --force.' % + except (Book.AlreadyExists, Picture.AlreadyExists): + print self.style.ERROR('%s: Book or Picture already imported. Skipping. To overwrite use --force.' % file_path) files_skipped += 1 diff --combined apps/catalogue/models.py index 3fd80ef8a,22cd0ea76..2b33964c2 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@@ -2,7 -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 @@@ -41,6 -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 @@@ -168,14 -174,41 +168,39 @@@ class Tag(TagBase) def url_chunk(self): return '/'.join((Tag.categories_dict[self.category], self.slug)) + @staticmethod + def tags_from_info(info): + from slughifi import slughifi + from sortify import sortify + meta_tags = [] + categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch')) + for field_name, category in categories: + try: + tag_names = getattr(info, field_name) + except: + tag_names = [getattr(info, category)] + for tag_name in tag_names: + tag_sort_key = tag_name + if category == 'author': + tag_sort_key = tag_name.last_name + tag_name = ' '.join(tag_name.first_names) + ' ' + tag_name.last_name + tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category) + if created: + tag.name = tag_name + tag.sort_key = sortify(tag_sort_key.lower()) + tag.save() + meta_tags.append(tag) + return meta_tags + + 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 + # BookMedia case + ext = media.formats[media.type].ext if media is None or not media.name: name = slughifi(filename.split(".")[0]) else: @@@ -212,16 -245,7 +237,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) @@@ -334,9 -358,8 +359,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) @@@ -433,14 -456,14 +458,14 @@@ 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) @@@ -484,12 -507,14 +509,12 @@@ # 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())) @@@ -503,22 -528,17 +528,22 @@@ cache.set(cache_key, short_html, CACHE_FOREVER) return mark_safe(short_html) - @property - def root_ancestor(self): - """ returns the oldest ancestor """ + def mini_box(self): + if self.id: + cache_key = "Book.mini_boxs/%d" % (self.id, ) + short_html = cache.get(cache_key) + else: + short_html = None - if not hasattr(self, '_root_ancestor'): - book = self - while book.parent: - book = book.parent - self._root_ancestor = book - return self._root_ancestor + if short_html is None: + authors = self.tags.filter(category='author') + short_html = unicode(render_to_string('catalogue/book_mini_box.html', + {'book': self, 'authors': authors, 'STATIC_URL': settings.STATIC_URL})) + + if self.id: + cache.set(cache_key, short_html, CACHE_FOREVER) + return mark_safe(short_html) def has_description(self): return len(self.description) > 0 @@@ -526,6 -546,11 +551,6 @@@ 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' @@@ -592,15 -617,34 +617,15 @@@ # 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) @@@ -712,7 -756,6 +737,6 @@@ def from_text_and_meta(cls, raw_file, book_info, overwrite=False, build_epub=True, build_txt=True, build_pdf=True, build_mobi=True): import re - from slughifi import slughifi from sortify import sortify # check for parts before we do anything @@@ -747,24 -790,7 +771,7 @@@ book.set_extra_info_value(book_info.to_dict()) book.save() - meta_tags = [] - categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch')) - for field_name, category in categories: - try: - tag_names = getattr(book_info, field_name) - except: - tag_names = [getattr(book_info, category)] - for tag_name in tag_names: - tag_sort_key = tag_name - if category == 'author': - tag_sort_key = tag_name.last_name - tag_name = ' '.join(tag_name.first_names) + ' ' + tag_name.last_name - tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category) - if created: - tag.name = tag_name - tag.sort_key = sortify(tag_sort_key.lower()) - tag.save() - meta_tags.append(tag) + meta_tags = Tag.tags_from_info(book_info) book.tags = set(meta_tags + book_shelves) @@@ -786,16 -812,17 +793,16 @@@ 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] @@@ -965,7 -992,7 +972,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 --combined lib/librarian index 4077ffb3c,a3c860f00..05b19dad8 --- a/lib/librarian +++ b/lib/librarian @@@ -1,1 -1,1 +1,1 @@@ - Subproject commit 4077ffb3cbd868df95239898563508b64e6d6ecf -Subproject commit a3c860f00c7d12ae5852ddab056c98f52ee43072 ++Subproject commit 05b19dad8ca44136e064abcc6beff5dac4489c60 diff --combined wolnelektury/settings.py index bd4e8a0b4,7ac3cd1eb..0692cc7ed --- a/wolnelektury/settings.py +++ b/wolnelektury/settings.py @@@ -151,6 -151,7 +151,7 @@@ INSTALLED_APPS = 'sponsors', 'stats', 'suggest', + 'picture', ] #CACHE_BACKEND = 'locmem:///?max_entries=3000' @@@ -160,13 -161,7 +161,13 @@@ CACHE_MIDDLEWARE_ANONYMOUS_ONLY=Tru # CSS and JavaScript file groups COMPRESS_CSS = { 'all': { - 'source_filenames': ('css/master.css', 'css/jquery.autocomplete.css', 'css/jquery.countdown.css', 'css/master.plain.css', 'css/sponsors.css', 'css/facelist_2-0.css',), + #'source_filenames': ('css/master.css', 'css/jquery.autocomplete.css', 'css/jquery.countdown.css', 'css/master.plain.css', 'css/sponsors.css', 'css/facelist_2-0.css',), + 'source_filenames': [ + 'css/base.css', + 'css/header.css', + 'css/main_page.css', + 'css/book_box.css', + ], 'output_filename': 'css/all.min?.css', }, 'book': { @@@ -180,33 -175,29 +181,33 @@@ } COMPRESS_JS = { - 'jquery': { - 'source_filenames': ('js/jquery.js',), - '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', - 'js/jquery.countdown-es.js', 'js/jquery.countdown-lt.js', - 'js/jquery.countdown-ru.js', 'js/jquery.countdown-fr.js', - 'js/jquery.cycle.min.js', - 'js/jquery.jqmodal.js', 'js/jquery.labelify.js', 'js/catalogue.js', - ), - 'output_filename': 'js/all?.min.js', - }, - 'book': { - 'source_filenames': ('js/jquery.eventdelegation.js', 'js/jquery.scrollto.js', 'js/jquery.highlightfade.js', 'js/book.js',), - 'output_filename': 'js/book?.min.js', - }, - 'book_ie': { - 'source_filenames': ('js/ierange-m2.js',), - 'output_filename': 'js/book_ie?.min.js', - } + #~ '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', + #~ 'js/jquery.countdown-es.js', 'js/jquery.countdown-lt.js', + #~ 'js/jquery.countdown-ru.js', 'js/jquery.countdown-fr.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': ('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': ('js/ierange-m2.js',), + #~ 'source_filenames': [], + #~ 'output_filename': 'js/book_ie?.min.js', + #~ } }