def form_valid(self, form): logger.debug('ImporterView::form_valid') book_file = form.cleaned_data.get('book_file') ext = get_file_extension(book_file.name) logger.debug('ImporterView::Importing file extension is "{}".'.format(ext.encode('utf8'))) default_book_title = self.get_default_title(book_file, ext) book_title = form.cleaned_data.get('book_title', default_book_title) logger.debug('ImporterView::book_title="{}" default_book_title="{}".'.format( book_title.encode('utf8'), default_book_title.encode('utf8'))) # in case book title in form is empty string if len(book_title) == 0: book_title = default_book_title if not check_book_availability(book_title): registered = Book.objects.filter(title__startswith=book_title).count() book_title = '%s %s' % (book_title, registered) logger.debug('ImporterView::Checking book availability: "{}".'.format(book_title.encode('utf8'))) book_url = booktype_slugify(book_title) book = create_book(self.request.user, book_title, book_url=book_url) logger.debug('ImporterView::Book created with url title="{}".'.format(book_url)) # check if book will be hidden and set to book book.hidden = form.cleaned_data.get('hidden') book.save() notifier = CollectNotifier() delegate = Delegate() response = {} try: book_importer = importer_utils.get_importer_module(ext) except KeyError: logger.error('ImporterView::No importer for this extension') response_data = dict(errors=[ugettext('Extension not supported!')]) return self.render_json_response(response_data) try: book_importer( book_file, book, notifier=notifier, delegate=delegate) logger.debug('ImporterView::Book imported.') response['url'] = reverse('reader:infopage', args=[book.url_title]) except Exception as e: logger.error('ImporterView::Some kind of error while importing book.') logger.exception(e) notifier.errors.append(str(e)) response['infos'] = notifier.infos response['warnings'] = notifier.warnings response['errors'] = notifier.errors return self.render_json_response(response)
def create(self, validated_data): n = Book.objects.count() book_title = validated_data['title'] owner = validated_data['owner'] url_title = '%s-%s' % (n, booktype_slugify(book_title)) book = create_book(owner, book_title, book_url=url_title) book.language = validated_data.get('language', None) book.save() import_book_url = validated_data.get('import_book_url') import_format = validated_data.get('import_book_format') if import_book_url: book_file = self._get_book_file(import_book_url) try: book_importer = importer_utils.get_importer_module( import_format) except Exception as err: error = "Wrong importer format {}".format(err) logger.warn('BookCreateSerializer create: {}'.format(error)) raise serializers.ValidationError(error) delegate = Delegate() notifier = CollectNotifier() try: book_importer(book_file, book, notifier=notifier, delegate=delegate) except Exception as err: error_msg = "Unexpected error while importing the file {}".format( err) logger.warn( 'BookCreateSerializer create: {}'.format(error_msg)) raise APIException(error_msg) if len(notifier.errors) > 0: err = "\n".join(notifier.errors) error_msg = "Something went wrong: {}".format(err) logger.warn( 'BookCreateSerializer create: {}'.format(error_msg)) raise APIException(error_msg) return book
def save_settings(self, request): book = create_book(self.cleaned_data['owner'], self.cleaned_data['title']) book.license = self.cleaned_data['license'] book.description = self.cleaned_data['description'] book.hidden = self.cleaned_data['is_hidden'] book.save() if 'cover' in self.files: try: fh, fname = misc.save_uploaded_as_file(self.files['cover']) book.set_cover(fname) os.unlink(fname) except: pass book.save() return book
def save_settings(self, request): book = create_book( self.cleaned_data['owner'], self.cleaned_data['title'] ) book.license = self.cleaned_data['license'] book.description = self.cleaned_data['description'] book.hidden = self.cleaned_data['is_hidden'] book.save() if 'cover' in self.files: try: fh, fname = misc.save_uploaded_as_file(self.files['cover']) book.set_cover(fname) os.unlink(fname) except: pass book.save() return book
def create(self, validated_data): n = Book.objects.count() book_title = validated_data['title'] owner = validated_data['owner'] url_title = '%s-%s' % (n, booktype_slugify(book_title)) book = create_book(owner, book_title, book_url=url_title) book.language = validated_data.get('language', None) book.save() import_book_url = validated_data.get('import_book_url') import_format = validated_data.get('import_book_format') if import_book_url: book_file = self._get_book_file(import_book_url) try: book_importer = importer_utils.get_importer_module(import_format) except Exception as err: error = "Wrong importer format {}".format(err) logger.warn('BookCreateSerializer create: {}'.format(error)) raise serializers.ValidationError(error) delegate = Delegate() notifier = CollectNotifier() try: book_importer(book_file, book, notifier=notifier, delegate=delegate) except Exception as err: error_msg = "Unexpected error while importing the file {}".format(err) logger.warn('BookCreateSerializer create: {}'.format(error_msg)) raise APIException(error_msg) if len(notifier.errors) > 0: err = "\n".join(notifier.errors) error_msg = "Something went wrong: {}".format(err) logger.warn('BookCreateSerializer create: {}'.format(error_msg)) raise APIException(error_msg) return book
def post(self, request, *args, **kwargs): book = create_book(request.user, request.POST.get('title')) lic = License.objects.get(abbrevation=request.POST.get('license')) book.license = lic book.description = request.POST.get('description', '') book.hidden = (request.POST.get('hidden', None) == 'on') if 'cover' in request.FILES: try: fh, fname = misc.save_uploaded_as_file(request.FILES['cover']) book.setCover(fname) os.unlink(fname) except: pass book.save() return render(request, 'account/create_book_redirect.html', { "request": request, "book": book })
def post(self, request, *args, **kwargs): book = create_book(request.user, request.POST.get('title')) lic = License.objects.get(abbrevation=request.POST.get('license')) book.license = lic book.description = request.POST.get('description', '') book.hidden = (request.POST.get('hidden', None) == 'on') if 'cover' in request.FILES: try: fh, fname = misc.save_uploaded_as_file(request.FILES['cover']) book.setCover(fname) os.unlink(fname) except: pass book.save() return render( request, 'account/create_book_redirect.html', {"request": request, "book": book} )
def importBookFromFile(user, zname, createTOC=False, **extraOptions): """Create a new book from a bookizip filename""" from booki.utils.log import logChapterHistory # unzip it zf = zipfile.ZipFile(zname) # load info.json info = json.loads(zf.read('info.json')) logWarning("Loaded json file %r" % info) metadata = info['metadata'] manifest = info['manifest'] TOC = info['TOC'] if extraOptions.get('book_title', None): bookTitle = extraOptions['book_title'] else: bookTitle = get_metadata(metadata, 'title', ns=DC)[0] bookTitle = makeTitleUnique(bookTitle) logWarning("Chose unique book title %r" % bookTitle) if extraOptions.get('book_url', None): bookURL = extraOptions['book_url'] else: bookURL = None book = create_book(user, bookTitle, status="new", bookURL=bookURL) if extraOptions.get("hidden"): book.hidden = True book.save() # this is for Table of Contents p = re.compile('\ssrc="(.*)"') # what if it does not have status "new" stat = models.BookStatus.objects.filter(book=book, name="new")[0] chapters = getChaptersFromTOC(TOC) n = len(chapters) + 1 #is +1 necessary? now = datetime.datetime.now() for chapterName, chapterFile, is_section in chapters: urlName = booktype_slugify(chapterName) if is_section: # create section if createTOC: c = models.BookToc(book=book, version=book.version, name=chapterName, chapter=None, weight=n, typeof=2) c.save() n -= 1 else: # create chapter # check if i can open this file at all content = zf.read(chapterFile) #content = p.sub(r' src="../\1"', content) chapter = models.Chapter(book=book, version=book.version, url_title=urlName, title=chapterName, status=stat, content=content, created=now, modified=now) chapter.save() history = logChapterHistory(chapter=chapter, content=content, user=user, comment="", revision=chapter.revision) if createTOC: c = models.BookToc(book=book, version=book.version, name=chapterName, chapter=chapter, weight=n, typeof=1) c.save() n -= 1 stat = models.BookStatus.objects.filter(book=book, name="new")[0] from django.core.files import File for item in manifest.values(): if item["mimetype"] != 'text/html': attachmentName = item['url'] if attachmentName.startswith("static/"): att = models.Attachment(book=book, version=book.version, status=stat) s = zf.read(attachmentName) f = StringIO(s) f2 = File(f) f2.size = len(s) att.attachment.save(os.path.basename(attachmentName), f2, save=False) att.save() f.close() # metadata for namespace in metadata: # namespace is something like "http://purl.org/dc/elements/1.1/" or "" # in the former case, preepend it to the name, in {}. ns = ('{%s}' % namespace if namespace else '') for keyword, schemes in metadata[namespace].iteritems(): for scheme, values in schemes.iteritems(): #schema, if it is set, describes the value's format. #for example, an identifier might be an ISBN. sc = ('{%s}' % scheme if scheme else '') key = "%s%s%s" % (ns, keyword, sc) for v in values: if not v: continue try: info = models.Info(book=book, name=key) if len(v) >= 2500: info.value_text = v info.kind = 2 else: info.value_string = v info.kind = 0 info.save() except: # For now just ignore any kind of error here. # Considering we don't handle metadata as we # should it is not such a problem. pass zf.close() return book
def post(self, request, *args, **kwargs): # TODO: convert this into an atomic view # TODO: use the form class to achieve this process and simplify this view and add validations # TODO: we should print warnings so user knows what's going on data = request.POST book = create_book(request.user, data.get('title')) license = License.objects.get(abbrevation=data.get('license')) language = Language.objects.get(abbrevation=data.get('language')) # STEP 1: Details book.author = data.get('author') book.license = license book.language = language book.hidden = (data.get('visible_to_everyone', None) == 'off') book.description = data.get('description', '') # STEP 2: Metadata metaform = MetadataForm(book=book, data=data) if metaform.is_valid(): metaform.save_settings(book, request) else: pass # STEP 3: Creation mode creation_mode = data.get('creation_mode', 'scratch') if creation_mode == 'based_on_book': try: base_book = Book.objects.get(id=request.POST.get('base_book')) base_book_version = base_book.get_version(None) result = import_based_on_book(base_book_version, book) except Book.DoesNotExist: logger.warn("Provided base book was not found") elif creation_mode == 'based_on_skeleton': try: base_skeleton = BookSkeleton.objects.get( id=request.POST.get('base_skeleton')) result = import_based_on_epub(base_skeleton.skeleton_file, book) except BookSkeleton.DoesNotExist: logger.warn("Provided base skeleton was not found") elif creation_mode == 'based_on_file': import_file = request.FILES.get('import_file') if import_file is not None: try: result = import_based_on_file(import_file, book) # noqa except Exception as err: logger.error( "ImportError: Something went wrong importing file. Msg %s" % err) # STEP 4: Book Cover if 'cover_image' in request.FILES: # first we create a cover registry and upload the file file_data = request.FILES['cover_image'] filename = file_data.name cover_license = License.objects.get( abbrevation=data.get('cover_license')) cover = BookCover(book=book, user=request.user, cid=uuid.uuid4().hex, title=data.get('cover_title'), filename=filename[:250], creator=data.get('cover_creator', '')[:40], license=cover_license, approved=False) cover.save() # now save the cover attachment cover.attachment.save(filename, file_data, save=False) cover.save() # and then finally, we set the book thumbnail try: fh, fname = misc.save_uploaded_as_file(file_data) book.set_cover(fname) os.unlink(fname) except: pass book.save() redirect_url = reverse('reader:infopage', args=[book.url_title]) return HttpResponse(json.dumps({'redirect': redirect_url}), 'application/json')
def importBookFromFile(user, zname, createTOC=False, **extraOptions): """Create a new book from a bookizip filename""" from booki.utils.log import logChapterHistory # unzip it zf = zipfile.ZipFile(zname) # load info.json info = json.loads(zf.read('info.json')) logWarning("Loaded json file %r" % info) metadata = info['metadata'] manifest = info['manifest'] TOC = info['TOC'] if extraOptions.get('book_title', None): bookTitle = extraOptions['book_title'] else: bookTitle = get_metadata(metadata, 'title', ns=DC)[0] bookTitle = makeTitleUnique(bookTitle) logWarning("Chose unique book title %r" % bookTitle) if extraOptions.get('book_url', None): bookURL = extraOptions['book_url'] else: bookURL = None book = create_book(user, bookTitle, status = "new", bookURL = bookURL) if extraOptions.get("hidden"): book.hidden = True book.save() # this is for Table of Contents p = re.compile('\ssrc="(.*)"') # what if it does not have status "new" stat = models.BookStatus.objects.filter(book=book, name="new")[0] chapters = getChaptersFromTOC(TOC) n = len(chapters) + 1 #is +1 necessary? now = datetime.datetime.now() for chapterName, chapterFile, is_section in chapters: urlName = booktype_slugify(chapterName) if is_section: # create section if createTOC: c = models.BookToc(book = book, version = book.version, name = chapterName, chapter = None, weight = n, typeof = 2) c.save() n -= 1 else: # create chapter # check if i can open this file at all content = zf.read(chapterFile) #content = p.sub(r' src="../\1"', content) chapter = models.Chapter(book = book, version = book.version, url_title = urlName, title = chapterName, status = stat, content = content, created = now, modified = now) chapter.save() history = logChapterHistory(chapter = chapter, content = content, user = user, comment = "", revision = chapter.revision) if createTOC: c = models.BookToc(book = book, version = book.version, name = chapterName, chapter = chapter, weight = n, typeof = 1) c.save() n -= 1 stat = models.BookStatus.objects.filter(book=book, name="new")[0] from django.core.files import File for item in manifest.values(): if item["mimetype"] != 'text/html': attachmentName = item['url'] if attachmentName.startswith("static/"): att = models.Attachment(book = book, version = book.version, status = stat) s = zf.read(attachmentName) f = StringIO(s) f2 = File(f) f2.size = len(s) att.attachment.save(os.path.basename(attachmentName), f2, save=False) att.save() f.close() # metadata for namespace in metadata: # namespace is something like "http://purl.org/dc/elements/1.1/" or "" # in the former case, preepend it to the name, in {}. ns = ('{%s}' % namespace if namespace else '') for keyword, schemes in metadata[namespace].iteritems(): for scheme, values in schemes.iteritems(): #schema, if it is set, describes the value's format. #for example, an identifier might be an ISBN. sc = ('{%s}' % scheme if scheme else '') key = "%s%s%s" % (ns, keyword, sc) for v in values: if not v: continue try: info = models.Info(book=book, name=key) if len(v) >= 2500: info.value_text = v info.kind = 2 else: info.value_string = v info.kind = 0 info.save() except: # For now just ignore any kind of error here. # Considering we don't handle metadata as we # should it is not such a problem. pass zf.close() return book
def post(self, request, *args, **kwargs): # TODO: convert this into an atomic view # TODO: use the form class to achieve this process and simplify this view and add validations # TODO: we should print warnings so user knows what's going on data = request.POST book = create_book(request.user, data.get('title')) license = License.objects.get(abbrevation=data.get('license')) language = Language.objects.get(abbrevation=data.get('language')) # STEP 1: Details book.author = data.get('author') book.license = license book.language = language book.hidden = (data.get('visible_to_everyone', None) == 'off') book.description = data.get('description', '') # STEP 2: Metadata metaform = MetadataForm(book=book, data=data) if metaform.is_valid(): metaform.save_settings(book, request) else: pass # STEP 3: Creation mode creation_mode = data.get('creation_mode', 'scratch') if creation_mode == 'based_on_book': try: base_book = Book.objects.get(id=request.POST.get('base_book')) base_book_version = base_book.get_version(None) result = import_based_on_book(base_book_version, book) except Book.DoesNotExist: logger.warn("Provided base book was not found") elif creation_mode == 'based_on_skeleton': try: base_skeleton = BookSkeleton.objects.get(id=request.POST.get('base_skeleton')) result = import_based_on_epub(base_skeleton.skeleton_file, book) except BookSkeleton.DoesNotExist: logger.warn("Provided base skeleton was not found") elif creation_mode == 'based_on_file': import_file = request.FILES.get('import_file') if import_file is not None: try: result = import_based_on_file(import_file, book) # noqa except Exception as err: logger.error("ImportError: Something went wrong importing file. Msg %s" % err) # STEP 4: Book Cover if 'cover_image' in request.FILES: # first we create a cover registry and upload the file file_data = request.FILES['cover_image'] filename = file_data.name cover_license = License.objects.get(abbrevation=data.get('cover_license')) cover = BookCover( book=book, user=request.user, cid=uuid.uuid4().hex, title=data.get('cover_title'), filename=filename[:250], creator=data.get('cover_creator', '')[:40], license=cover_license, approved=False) cover.save() # now save the cover attachment cover.attachment.save(filename, file_data, save=False) cover.save() # and then finally, we set the book thumbnail try: fh, fname = misc.save_uploaded_as_file(file_data) book.set_cover(fname) os.unlink(fname) except: pass book.save() redirect_url = reverse('reader:infopage', args=[book.url_title]) return HttpResponse(json.dumps({'redirect': redirect_url}), 'application/json')
def form_valid(self, form): logger.debug('ImporterView::form_valid') book_file = self.request.FILES['book_file'] ext = self.file_extension(book_file.name) logger.debug('ImporterView::Importing file extension is "{}".'.format(ext.encode('utf8'))) temp_file = tempfile.NamedTemporaryFile( prefix='importing-', suffix='%s' % ext, delete=False) temp_file = open(temp_file.name, 'wb+') logger.debug('ImporterView::Saving temporary file {}.'.format(temp_file.name.encode('utf8'))) for chunk in book_file.chunks(): temp_file.write(chunk) temp_file.close() temp_file = temp_file.name default_book_title = self.get_default_title(temp_file, ext) book_title = form.cleaned_data.get('book_title', default_book_title) logger.debug('ImporterView::book_title="{}"" default_book_title="{}".'.format(book_title.encode('utf8'), default_book_title.encode('utf8'))) # in case book title in form is empty string if len(book_title) == 0: book_title = default_book_title if not check_book_availability(book_title): registered = Book.objects.filter( title__startswith=book_title).count() book_title = '%s %s' % (book_title, registered) logger.debug('ImporterView::Checking book availability: "{}".'.format(book_title.encode('utf8'))) book_url = booktype_slugify(book_title) book = create_book( self.request.user, book_title, book_url=book_url) logger.debug('ImporterView::Book created with url title="{}".'.format(book_url)) # check if book will be hidden and set to book book_hidden = form.cleaned_data.get('hidden') if book_hidden: book.hidden = book_hidden book.save() logger.debug('ImporterView::Setting book hidden.') else: logger.debug('ImporterView::Setting book visible.') notifier = CollectNotifier() delegate = Delegate() response = {} try: book_importer = self.get_importer(ext) except KeyError: logger.error('ImporterView::No importer for this extension') response_data = { 'errors': [_('Extension not supported!')], } return self.render_json_response(response_data) try: book_importer( temp_file, book, notifier=notifier, delegate=delegate ) logger.debug('ImporterView::Book imported.') response['url'] = reverse('reader:infopage', args=[book.url_title]) except Exception as e: logger.error('ImporterView::Some kind of error while importing book.') logger.exception(e) notifier.errors.append(str(e)) response['infos'] = notifier.infos response['warnings'] = notifier.warnings response['errors'] = notifier.errors return self.render_json_response(response)
def form_valid(self, form): logger.debug('ImporterView::form_valid') book_file = self.request.FILES['book_file'] ext = self.file_extension(book_file.name) logger.debug('ImporterView::Importing file extension is "{}".'.format( ext.encode('utf8'))) temp_file = tempfile.NamedTemporaryFile(prefix='importing-', suffix='%s' % ext, delete=False) temp_file = open(temp_file.name, 'wb+') logger.debug('ImporterView::Saving temporary file {}.'.format( temp_file.name.encode('utf8'))) for chunk in book_file.chunks(): temp_file.write(chunk) temp_file.close() temp_file = temp_file.name default_book_title = self.get_default_title(temp_file, ext) book_title = form.cleaned_data.get('book_title', default_book_title) logger.debug( 'ImporterView::book_title="{}"" default_book_title="{}".'.format( book_title.encode('utf8'), default_book_title.encode('utf8'))) # in case book title in form is empty string if len(book_title) == 0: book_title = default_book_title if not check_book_availability(book_title): registered = Book.objects.filter( title__startswith=book_title).count() book_title = '%s %s' % (book_title, registered) logger.debug( 'ImporterView::Checking book availability: "{}".'.format( book_title.encode('utf8'))) book_url = booktype_slugify(book_title) book = create_book(self.request.user, book_title, book_url=book_url) logger.debug( 'ImporterView::Book created with url title="{}".'.format(book_url)) # check if book will be hidden and set to book book_hidden = form.cleaned_data.get('hidden') if book_hidden: book.hidden = book_hidden book.save() logger.debug('ImporterView::Setting book hidden.') else: logger.debug('ImporterView::Setting book visible.') notifier = CollectNotifier() delegate = Delegate() response = {} try: book_importer = self.get_importer(ext) except KeyError: logger.error('ImporterView::No importer for this extension') response_data = { 'errors': [_('Extension not supported!')], } return self.render_json_response(response_data) try: book_importer(temp_file, book, notifier=notifier, delegate=delegate) logger.debug('ImporterView::Book imported.') response['url'] = reverse('reader:infopage', args=[book.url_title]) except Exception as e: logger.error( 'ImporterView::Some kind of error while importing book.') logger.exception(e) notifier.errors.append(str(e)) response['infos'] = notifier.infos response['warnings'] = notifier.warnings response['errors'] = notifier.errors return self.render_json_response(response)