def handle(self, *args, **options): verbosity = int(options['verbosity']) # 1 = normal, 0 = minimal, 2 = all v_normal = 1 v_all = 2 if options['pdf_only'] and options['skip_pdf_reload']: raise CommandError("Options -s and -p are not compatible") # check for required settings if not hasattr(settings, 'EXISTDB_ROOT_COLLECTION') or not settings.EXISTDB_ROOT_COLLECTION: raise CommandError("EXISTDB_ROOT_COLLECTION setting is missing") return if len(args): files = args else: # Note: copied from prep_ead manage command; move somewhere common? files = set() svn = svn_client() for archive in Archive.objects.all(): # update to make sure we have latest version of everything svn.update(str(archive.svn_local_path)) # apparently can't handle unicode files.update(set(glob.iglob(os.path.join(archive.svn_local_path, '*.xml')))) if verbosity == v_all: print 'Documents will be loaded to configured eXist collection: %s' \ % settings.EXISTDB_ROOT_COLLECTION if options['skip_pdf_reload']: print "** Skipping PDFs cache reload" db = ExistDB() loaded = 0 errored = 0 pdf_tasks = {} start_time = datetime.now() if not options['pdf_only']: # unless PDF reload only has been specified, load files for file in files: try: # full path location where file will be loaded in exist db collection dbpath = settings.EXISTDB_ROOT_COLLECTION + "/" + os.path.basename(file) errors = check_ead(file, dbpath) if errors: # report errors, don't load errored += 1 print "Error: %s does not pass publication checks; not loading to eXist." % file if verbosity >= v_normal: print " Errors found:" for err in errors: print " %s" % err else: with open(file, 'r') as eadfile: success = db.load(eadfile, dbpath, overwrite=True) if success: loaded += 1 if verbosity >= v_normal: print "Loaded %s" % file # load the file as a FindingAid object to get the eadid for PDF reload ead = load_xmlobject_from_file(file, FindingAid) # trigger PDF regeneration in the cache and store task result # - unless user has requested PDF reload be skipped if not options['skip_pdf_reload']: pdf_tasks[ead.eadid.value] = reload_cached_pdf.delay(ead.eadid.value) # NOTE: unlike the web admin publish, this does not # generate TaskResult db records; task outcomes will be # checked & reported before the script finishes else: errored += 1 print "Error: failed to load %s to eXist" % file except ExistDBException, e: print "Error: failed to load %s to eXist" % file print e.message() errored += 1 # output a summary of what was done print "%d document%s loaded" % (loaded, 's' if loaded != 1 else '') print "%d document%s with errors" % (errored, 's' if errored != 1 else '')
def publish(request): """ Admin publication form. Allows publishing an EAD file by updating or adding it to the configured eXist database so it will be immediately visible on the public site. Files can only be published if they pass an EAD sanity check, implemented in :meth:`~findingaids.fa_admin.utils.check_ead`. On POST, sanity-check the EAD file specified in request from the configured and (if it passes all checks), publish it to make it immediately visible on the site. If publish is successful, redirects the user to main admin page with a success message that links to the published document on the site. If the sanity-check fails, displays a page with any problems found. """ # formerly supported publish from filename, but now only supports # publish from preview if 'preview_id' not in request.POST: messages.error(request, "No preview document specified for publication") return HttpResponseSeeOtherRedirect(reverse('fa-admin:index')) id = request.POST['preview_id'] # retrieve info about the document from preview collection try: # because of the way existdb.query.queryset constructs returns with 'also' fields, # it is simpler and better to retrieve document name separately ead = get_findingaid(id, preview=True) ead_docname = get_findingaid(id, preview=True, only=['document_name']) filename = ead_docname.document_name except (ExistDBException, Http404): # not found in exist OR permission denied messages.error(request, '''Publish failed. Could not retrieve <b>%s</b> from preview collection. Please reload and try again.''' % id) # if ead could not be retrieved from preview mode, skip processing return HttpResponseSeeOtherRedirect(reverse('fa-admin:index')) # determine archive this ead is associated with archive = None if not ead.repository: messages.error(request, '''Publish failed. Could not determine which archive <b>%s</b> belongs to. Please update subarea, reload, and try again.''' % id) else: archive_name = ead.repository[0] # NOTE: EAD supports multiple subarea tags, but in practice we only # use one, so it should be safe to assume the first should be used for permissions try: archive = Archive.objects.get(name=archive_name) except ObjectDoesNotExist: messages.error(request, '''Publish failed. Could not find archive <b>%s</b>.''' % archive_name) # bail out if archive could not be identified if archive is None: return HttpResponseSeeOtherRedirect(reverse('fa-admin:index')) # check that user is allowed to publish this document if not archive_access(request.user, archive.slug): messages.error(request, '''You do not have permission to publish <b>%s</b> materials.''' \ % archive.label) return HttpResponseSeeOtherRedirect(reverse('fa-admin:index')) errors = [] try: # NOTE: *not* using serialized xml here, because it may introduce # whitespace errors not present in the original file. ok, response, dbpath, fullpath = _prepublication_check(request, filename, archive) if ok is not True: # publication check failed - do not publish return response # only load to exist if there are no errors found db = ExistDB() # get information to determine if an existing file is being replaced replaced = db.describeDocument(dbpath) try: # move the document from preview collection to configured public collection success = db.moveDocument(settings.EXISTDB_PREVIEW_COLLECTION, settings.EXISTDB_ROOT_COLLECTION, filename) # FindingAid instance ead already set above except ExistDBException, e: # special-case error message errors.append("Failed to move document %s from preview collection to main collection." \ % filename) # re-raise and let outer exception handling take care of it raise e except ExistDBException as err: errors.append(err.message()) success = False if success: # request the cache to reload the PDF - queue asynchronous task result = reload_cached_pdf.delay(ead.eadid.value) task = TaskResult(label='PDF reload', object_id=ead.eadid.value, url=reverse('fa:findingaid', kwargs={'id': ead.eadid.value}), task_id=result.task_id) task.save() ead_url = reverse('fa:findingaid', kwargs={'id': ead.eadid.value}) change = "updated" if replaced else "added" messages.success(request, 'Successfully %s <b>%s</b>. View <a href="%s">%s</a>.' % (change, filename, ead_url, unicode(ead.unittitle))) # redirect to main admin page and display messages return HttpResponseSeeOtherRedirect(reverse('fa-admin:index')) else: return render(request, 'fa_admin/publish-errors.html', {'errors': errors, 'filename': filename, 'mode': 'publish', 'exception': err})
settings.EXISTDB_ROOT_COLLECTION, filename) # FindingAid instance ead already set above except ExistDBException, e: # special-case error message errors.append("Failed to move document %s from preview collection to main collection." \ % filename) # re-raise and let outer exception handling take care of it raise e except ExistDBException, e: errors.append(e.message()) success = False if success: # request the cache to reload the PDF - queue asynchronous task result = reload_cached_pdf.delay(ead.eadid.value) task = TaskResult(label='PDF reload', object_id=ead.eadid.value, url=reverse('fa:findingaid', kwargs={'id': ead.eadid.value}), task_id=result.task_id) task.save() ead_url = reverse('fa:findingaid', kwargs={'id': ead.eadid.value}) change = "updated" if replaced else "added" messages.success(request, 'Successfully %s <b>%s</b>. View <a href="%s">%s</a>.' % (change, filename, ead_url, unicode(ead.unittitle))) # redirect to main admin page and display messages return HttpResponseSeeOtherRedirect(reverse('fa-admin:index')) else: return render(request, 'fa_admin/publish-errors.html', {'errors': errors, 'filename': filename, 'mode': 'publish', 'exception': e})