def handle_post(self, params, context): context.update(self.build_form_context(params)) do_import = getparam('import', None, None, params) if do_import: self.set_next(BuildExploratourRecordsTask(self.handler, self.importer)) redirect(url("import", id=self.importer.id)) return render("import/choose-fields.html", context)
def create(self, **params): context = {} if cherrypy.request.method == "POST": # FIXME - check csrf token title = params.get('newcoll_title', u'').strip() parents = coll_parents_from_request() if getparam('create'): if title: id = create_collection(title, parents) gonext() redirect(url("colls-list", id=id)) else: context['error'] = "You must set a title for the collection" else: parents = [] allowable_parents = set( c.id for c in Collection.objects ) context.update(dict( parents = tuple(enumerate(parents)), allowable_parents = sorted(allowable_parents), collections = Collection.objects, )) return render("coll-new.html", context)
def imp(self, **params): stash = {} # Get any existing Importer imp = None imp_id = getintparam("id", None, stash, params) if imp_id is not None: imp = self.imports.get(imp_id, None) if imp is None: context = {} context['error'] = 'Unknown import ID' return render("import/choose-file.html", context) if imp is None: # No import in progress if cherrypy.request.method == "POST": return self.handle_import_start(params) elif cherrypy.request.method == "GET": return render("import/choose-file.html", {}) else: # Import in progress; let it handle the request. if cherrypy.request.method == "POST": if getparam("import_cancel", None): imp.cancel() redirect(url("home")) return imp.handle_post(params) elif cherrypy.request.method == "GET": return imp.handle_get(params) raise cherrypy.NotFound
def reorder(self, id, **params): if getparam('cancel') == '1': redirect(url("coll-view", id=id)) coll = get_or_404(Collection, id) context = {} if cherrypy.request.method == "POST": # FIXME - check csrf token order, ordering = coll_order_from_request() if getparam('submit') == '1': # save order coll.autoorder.ordering = ordering Collection.objects.set(coll) Collection.objects.flush() redirect(url("coll-view", id=id)) else: order = [] for field, dir in coll.autoorder.ordering: order.append((len(order), field, dir)) if not order: order.append((0, '', '')) context['coll'] = coll context['collorder'] = order return render("coll-reorder.html", context)
def handle_post(self, params, context): context.update(self.build_form_context(params)) do_import = getparam('import', None, None, params) if do_import: self.set_next(ImportPerformTask(self.handler, self.importer)) redirect(url("import", id=self.importer.id)) return render("import/choose-mappings.html", context)
def copy(self, id, **params): record = copy.deepcopy(get_or_404(Record, id)) del record.id Record.objects.set(record) Record.objects.flush() redirect(url("record-edit", id=record.id, tmplid=params.get('tmplid', ''), copyof=record.title))
def reindex(self, **params): stash = {} if cherrypy.request.method == "POST": progress = pool.get_progress(reindexer_id[0]) if progress.complete: reindexer_id[0] = pool.add_task(Reindexer()) redirect(url("reindex")) context = dict(progress = pool.get_progress(reindexer_id[0])) return render("reindex.html", context)
def export_backup(self, export_id=None, download=False, **params): # Read parameters first, to ensure they all get stashed. stash = {} # Make a new exporter, and get any parameters it needs into the stash. exp = Exporter.get('xml')() exp.read_params(stash, params) # Handle exports which are in progress, or have finished if export_id is not None: try: export_id = int(export_id) except ValueError: export_id = None if export_id is not None: try: running_exp = exports[export_id] except KeyError: # Invalid export id (most probably due to a server restart) running_exp = None if running_exp is not None: # Export in progress progress = pool.get_progress(export_id) context = dict(export_id=export_id, fmt='xml', progress=progress, stash=stash) if not progress.complete: return render('export/in_progress.html', context) if progress.failed: return render('export/failed.html', context) # Export complete if not download: # Display a "Export prepared" return render('export/complete.html', context) return running_exp.respond() # Read the set of things to export. search, desc, topcoll = self._get_export_records(stash, None, None, None, True) if not getparam('export', False, stash, params): # Not ready to start the export yet. context = dict( export_desc = desc, stash = stash, ) exp.add_to_context(context, search, stash, params) return render('backup/pick.html', context) # Start the exporter task = ExportRecords(exp, search) export_id = pool.add_task(task) exports[export_id] = task redirect(url("records-export-inprogress", export_id=export_id, fmt='xml', **stash))
def from_exploratour(self, **params): context = {} if cherrypy.request.method == "POST": imp = import_exploratour.start_import(params) if imp.error: context['error'] = imp.error return render("import/from-exploratour.html", context) self.imports[imp.id] = imp redirect(url("import-status", id=imp.id)) return render("import/from-exploratour.html", context)
def handle_import_start(self, params): """Handle a POST request that starts an import.""" if getparam("import_cancel", None): redirect(url("home")) imp = download.Importer() imp.start(params) if imp.error: context = {} context['error'] = imp.error return render("import/choose-file.html", context) self.imports[imp.id] = imp redirect(url("import", id=imp.id))
def list(self, **params): coll = get_lockto_coll() if coll is not None: redirect(url("coll-view", id=coll.id)) groups = [CollGroup(coll.id, coll.title, [coll.id]) for coll in Collection.objects if not coll.parents] groupid = getparam('groupid', '') filtered_groups = filter(lambda group: group.id == groupid, groups) if len(filtered_groups) > 0: currgroup = filtered_groups[0] elif len(groups) > 0: currgroup = groups[0] else: currgroup = None context = dict(groups=groups, currgroup=currgroup) return render("colls-list.html", context)
def _check_delete(self, id, page): params = cherrypy.request.params if params.get('delete', '') != '': tmpl = get_or_404(Template, id) context = dict(tmpl=tmpl, page=page) return render("tmpl-delete-confirm.html", context) if cherrypy.request.method == "POST": if params.get('delete_conf', '') != '': try: Template.objects.remove(id) Template.objects.flush() except KeyError: raise cherrypy.HTTPError(404) gonext() redirect(url("tmpls-list"))
def roots(self, **params): error = None if cherrypy.request.method == "POST": num = 0 roots_dict = {} roots = [] dupe_names = set() while True: name = params.get('rn%d' % num) path = params.get('rp%d' % num) num += 1 if name is None or path is None: break if name == '': if path != '': error = u'No name specified for path "%s"' % path else: if path == '': error = u'Empty path specified for name "%s"' % name if name == '' and path == '': continue if name != '' and name in roots_dict: dupe_names.add(name) path = path.strip() roots_dict[name] = path roots.append((num - 1, (name, path))) if dupe_names: if len(dupe_names) == 1: error = u"Duplicated name: \"%s\"" % tuple(dupe_names)[0] else: error = u"Duplicated names: \"%s\"" % u'\", \"'.join(sorted(dupe_names)) if error is None: settings = get_settings() settings.set_roots(roots_dict) Settings.objects.set(settings) Settings.objects.flush() redirect(url("settings-roots")) else: roots_dict = get_settings().get_roots() if not roots_dict: roots_dict = config.default_media_roots roots = tuple(enumerate(sorted(roots_dict.items()))) context = dict( error = error, roots = roots, ) return render("settings/roots.html", context)
def delete(self, id, **params): coll = get_or_404(Collection, id) if cherrypy.request.method == "POST": # FIXME - check csrf token if id: if params.get('delete_conf', '') == '': redirect(url("colls-list")) coll = get_or_404(Collection, id) # Remove the collection's parents coll.set_parents(()) Collection.objects.set(coll) # Remove the collection from its childrens parent lists. child_colls = coll.children for child in child_colls: cparents = set(child.parents) cparents.remove(id) child.set_parents(cparents) Collection.objects.set(child) # Iterate through the records in the collection, and remove the # collection from them. SearchCollection.checkpoint().wait() for record in SearchCollection.doc_type('record') \ .field.coll.is_in(id)[:]: try: record = record.object except KeyError: # Record is already gone - can't update it. # (This shouldn't happen, but do this check for # robustness.) continue record.collections = filter(lambda x: x != id, record.collections) Record.objects.set(record) Collection.objects.remove(id) Record.objects.flush() Collection.objects.flush() gonext() redirect(url("colls-list", id=coll.id)) elif cherrypy.request.method == "GET": context = dict(coll=coll) return render("coll-delete-confirm.html", context) raise cherrypy.HTTPError(404)
def reparent(self, id, **params): if getparam('cancel') == '1': redirect(url("coll-view", id=id)) coll = get_or_404(Collection, id) if cherrypy.request.method == "POST": # FIXME - check csrf token title = getparam('title') parents = coll_parents_from_request() if getparam('submit') == '1': # Save parents changed = coll.set_parents(filter(lambda x: x != '', parents)) if coll.title != title: coll.title = title Collection.objects.set(coll) Collection.objects.flush() Record.objects.flush() redirect(url("coll-view", id=id)) else: title = coll.title parents = [] for parent in coll.parents: parents.append(parent) if not parents: parents.append('') not_allowed = set(coll.ancestors) - set(coll.parents) not_allowed.add(id) allowable_parents = set( c.id for c in Collection.objects if c.id != id and id not in c.ancestors ) context = dict( title = title, coll = coll, parents = tuple(enumerate(parents)), allowable_parents = sorted(allowable_parents), collections = Collection.objects, ) return render("coll-reparent.html", context)
def thumbnail(self, path, width=64, height=64): if not mapper.exists(path): redirect(url("/static/icons/thumbs/missing.png")) width = int(width) height = int(height) # Note - the path supplied is supplied as a query parameter, not as # part of the path info in the URL, because otherwise cherrypy strips # out any double slashes, making it impossible to tell if the path # starts with a drivename (on windows) or with an absolute path which # should have a / inserted before it (on unix). try: data, ctype = thumbcache.get_data(mapper._map_path(path), width, height) cherrypy.response.headers["Content-Type"] = ctype return data except IOError: redirect(url("/static/icons/thumbs/broken.png"))
def _check_delete(self, id, page): params = cherrypy.request.params if params.get('delete', '') != '': record = get_or_404(Record, id) context = dict(record=record, page=page) return render("record-delete-confirm.html", context) if cherrypy.request.method == "POST": if params.get('delete_conf', '') != '': record = get_or_404(Record, id) #print "Old collections", record.collections record.collections = () # Set the record, to remove the collections Record.objects.set(record) Record.objects.remove(id) Record.objects.flush() Collection.objects.flush() gonext() redirect(url("search", act='search'))
def _get_export_records(self, stash, record_id, issearch, coll, incsubs): """Returns a search queryset, and a description of the export.""" # record_id is set to export a single record. if record_id is not None: search = SearchCollection.doc_type('record').field.id == record_id return search, "record with id %s" % record_id, None # if issearch is set, export the search results. if issearch is not None: params = SearchParams(stash) search_obj = Search(params) if not search_obj.validate(): redirect(url("search", **stash)) desc = "%d records found by search.\n" % search_obj.match_count return search_obj.query, desc + search_obj.query_desc, None # FIXME - allow selected records here. # If we've got no collection set, but have a lock, set the collection # to the locked one. lockedto = get_lockto_coll() if lockedto is not None and coll is None: coll = lockedto.id # coll is set to export a whole collection. if coll is not None: coll_obj = get_or_404(Collection, coll) search = coll_obj.items_from_search(incsubs=incsubs) desc = "all %d records from collection %s" % ( len(search), coll_obj.title ) if incsubs: desc += " (including subcollections)" return search, desc, coll_obj # If none of the above are set, export everything. return SearchCollection.doc_type('record').all()[:], "all records", None
def search(self, **params): stash = {} context = dict(stash=stash) params = SearchParams(stash) search = Search(params) if not search.validate(): # If the search doesn't validate, always go to the search entry # page. params.action = 'entry' search.add_to_context(context) context['showfull'] = int(getparam('showfull', '0', stash)) if params.action == 'search': return render("search.html", context) elif params.action == 'select': return render("search_select.html", context) elif params.action.startswith('createcoll'): if cherrypy.request.method != "POST": return render("search_createcoll.html", context) subact = params.action[11:] parents = [] for num in getorderparam('parent_order'): parent = getparam('parent%d' % num) if parent is None or parent == '': continue if subact == ('del_parent_%d' % num): continue parents.append(unicode(parent)) if subact == 'add_parent': parents.append(u'') context['parents'] = tuple(enumerate(parents)) context['allowable_parents'] = set( c.id for c in Collection.objects ) context['collections'] = Collection.objects if subact == 'do': newtitle = getparam('create_colltitle', '') if len(newtitle) == 0: context['error'] = "Cannot create collection with no title" return render("search_createcoll.html", context) coll = Collection.find_by_title(newtitle) if len(coll) != 0: context['error'] = "Collection with title %s already exists" % newtitle return render("search_createcoll.html", context) coll = Collection(None, None, newtitle) Collection.objects.set(coll) # Have to set the collection before setting the parents, to get # an ID for the parents to refer back to. coll.set_parents(filter(lambda x: x != '', parents)) Collection.objects.set(coll) Record.objects.flush() Collection.objects.flush() for record in search.query: record = record.object record.collections = record.collections + [coll.id] Record.objects.set(record) Record.objects.flush() Collection.objects.flush() redirect(url("coll-view", id=coll.id)) else: return render("search_createcoll.html", context) elif params.action == 'addtocoll': context['all_collections'] = Collection.objects if cherrypy.request.method != "POST": return render("search_addtocoll.html", context) newid = getparam('addto_collid', '') if len(newid) == 0: context['error'] = "Pick a collection to add to" return render("search_addtocoll.html", context) coll = Collection.objects.get(newid) for record in search.query: record = record.object record.collections = record.collections + [coll.id] Record.objects.set(record) Record.objects.flush() Collection.objects.flush() redirect(url("coll-view", id=coll.id)) return render("search_addtocoll.html", context) elif params.action == 'removefromcoll': context['all_collections'] = Collection.objects if cherrypy.request.method != "POST": return render("search_removefromcoll.html", context) newid = getparam('removefrom_collid', '') if len(newid) == 0: context['error'] = "Pick a collection to remove from" return render("search_removefromcoll.html", context) coll = Collection.objects.get(newid) for record in search.query: record = record.object record.collections = tuple(filter(lambda x: x != coll.id, record.collections)) Record.objects.set(record) Record.objects.flush() Collection.objects.flush() redirect(url("coll-view", id=coll.id)) return render("search_removefromcoll.html", context) else: context['all_collections'] = Collection.objects return render("search_entry.html", context)
def delete(self, id, **params): ret = self._check_delete(id, 'record-delete') if ret is not None: return ret redirect(url("record-view", id=id, tmplid=params.get('tmplid')))
def delete(self, id, **params): ret = self._check_delete(id, 'tmpl-delete') if ret is not None: return ret redirect(url("tmpl-view", id=id))
def export_records(self, export_id=None, fmt='rtf', download=False, **params): """Export a set of records. """ # Read parameters first, to ensure they all get stashed. stash = {} record_id = getparam('record_id', None, stash, params) issearch = getparam('issearch', None, stash, params) coll = getparam('coll', None, stash, params) incsubs = getintparam('incsubs', 1, stash, params) # Make a new exporter, and get any parameters it needs into the stash. try: exp = Exporter.get(fmt)() except KeyError: raise cherrypy.NotFound exp.read_params(stash, params) # Handle exports which are in progress, or have finished if export_id is not None: try: export_id = int(export_id) except ValueError: export_id = None if export_id is not None: try: running_exp = exports[export_id] except KeyError: # Invalid export id (most probably due to a server restart) running_exp = None if running_exp is not None: # Export in progress progress = pool.get_progress(export_id) context = dict(export_id=export_id, fmt=fmt, progress=progress, stash=stash) if not progress.complete: return render('export/in_progress.html', context) if progress.failed: return render('export/failed.html', context) # Export complete if not download: # Display a "Export prepared" return render('export/complete.html', context) return running_exp.respond() # Read the set of things to export. search, desc, topcoll = self._get_export_records(stash, record_id, issearch, coll, incsubs) if not getparam('export', False, stash, params): # Not ready to start the export yet. context = dict( fmts = Exporter.fmts(params), fmt = fmt, export_desc = desc, stash = stash, ) exp.add_to_context(context, search, stash, params) return render('export/pickfmt.html', context) # Start the exporter task = ExportRecords(exp, search) export_id = pool.add_task(task) exports[export_id] = task redirect(url("records-export-inprogress", export_id=export_id, fmt=fmt, **stash))
context['error'] = e.errormsg ok = False orig_record = get_or_404(Record, id) record = dict(inner_xml=params.get('inner_xml', None), collections=validator.collections, fieldnums=orig_record.fieldnums, walkfields=orig_record.walkfields, id=id, ) if ok and params.get('save', '') != '': Record.objects.set(record) Record.objects.flush() gonext() tmplid = params.get('tmplid', '') redirect(url("record-view", id=record.id, tmplid=tmplid)) context['record'] = record return context def tmpl_from_request(id, params): context = {} params, remcoll = handle_create_collection(params) validator = RecordValidator(params, remcoll) if validator.invalid_collections: return dict(invalid_collections=validator.invalid_collections) newid = params.get('newid') ok = True