Add support for "delete set" feature for main object index view

aka. "delete selected objects"
This commit is contained in:
Lance Edgar 2019-02-02 19:34:36 -06:00
parent 5ec11cf5b8
commit 84fc3e7d50

View file

@ -82,6 +82,7 @@ class MasterView(View):
editable = True
deletable = True
bulk_deletable = False
set_deletable = False
populatable = False
mergeable = False
downloadable = False
@ -326,6 +327,14 @@ class MasterView(View):
Return a dictionary of kwargs to be passed to the factory when creating
new grid instances.
"""
permission_prefix = self.get_permission_prefix()
checkboxes = self.checkboxes
if not checkboxes and self.mergeable and self.request.has_perm('{}.merge'.format(permission_prefix)):
checkboxes = True
if not checkboxes and self.set_deletable and self.request.has_perm('{}.delete_set'.format(permission_prefix)):
checkboxes = True
defaults = {
'model_class': getattr(self, 'model_class', None),
'width': 'full',
@ -335,8 +344,7 @@ class MasterView(View):
'pageable': self.pageable,
'extra_row_class': self.grid_extra_class,
'url': lambda obj: self.get_action_url('view', obj),
'checkboxes': self.checkboxes or (
self.mergeable and self.request.has_perm('{}.merge'.format(self.get_permission_prefix()))),
'checkboxes': checkboxes,
'checked': self.checked,
}
if 'main_actions' not in kwargs and 'more_actions' not in kwargs:
@ -1569,19 +1577,15 @@ class MasterView(View):
"""
Delete all records matching the current grid query
"""
if self.request.method == 'POST':
objects = self.get_effective_data()
key = '{}.bulk_delete'.format(self.model_class.__tablename__)
progress = SessionProgress(self.request, key)
thread = Thread(target=self.bulk_delete_thread, args=(objects, progress))
thread.start()
return self.render_progress(progress, {
'cancel_url': self.get_index_url(),
'cancel_msg': "Bulk deletion was canceled",
})
else:
self.request.session.flash("Sorry, you must POST to do a bulk delete operation")
return self.redirect(self.get_index_url())
objects = self.get_effective_data()
key = '{}.bulk_delete'.format(self.model_class.__tablename__)
progress = SessionProgress(self.request, key)
thread = Thread(target=self.bulk_delete_thread, args=(objects, progress))
thread.start()
return self.render_progress(progress, {
'cancel_url': self.get_index_url(),
'cancel_msg': "Bulk deletion was canceled",
})
def bulk_delete_objects(self, session, objects, progress=None):
@ -1626,6 +1630,26 @@ class MasterView(View):
progress.session['success_url'] = self.get_index_url()
progress.session.save()
def delete_set(self):
"""
View which can delete a specific set of records.
"""
# TODO: should have a cleaner way to parse object uuids?
uuids = self.request.POST.get('uuids')
if uuids:
uuids = uuids.split(',')
# TODO: probably need to allow override of fetcher callable
fetcher = lambda uuid: self.Session.query(self.model_class).get(uuid)
deleted = 0
for uuid in uuids:
obj = fetcher(uuid)
if obj:
self.delete_instance(obj)
deleted += 1
model_title_plural = self.get_model_title_plural()
self.request.session.flash("Deleted {} {}".format(deleted, model_title_plural))
return self.redirect(self.get_index_url())
def oneoff_import(self, importer, host_object=None):
"""
Basic helper method, to do a one-off import (or export, depending on
@ -3057,12 +3081,22 @@ class MasterView(View):
# bulk delete
if cls.bulk_deletable:
config.add_route('{}.bulk_delete'.format(route_prefix), '{}/bulk-delete'.format(url_prefix))
config.add_route('{}.bulk_delete'.format(route_prefix), '{}/bulk-delete'.format(url_prefix),
request_method='POST')
config.add_view(cls, attr='bulk_delete', route_name='{}.bulk_delete'.format(route_prefix),
permission='{}.bulk_delete'.format(permission_prefix))
config.add_tailbone_permission(permission_prefix, '{}.bulk_delete'.format(permission_prefix),
"Bulk delete {}".format(model_title_plural))
# delete set
if cls.set_deletable:
config.add_tailbone_permission(permission_prefix, '{}.delete_set'.format(permission_prefix),
"Delete set (selection) of {}".format(model_title_plural))
config.add_route('{}.delete_set'.format(route_prefix), '{}/delete-set'.format(url_prefix),
request_method='POST')
config.add_view(cls, attr='delete_set', route_name='{}.delete_set'.format(route_prefix),
permission='{}.delete_set'.format(permission_prefix))
# merge
if cls.mergeable:
config.add_route('{}.merge'.format(route_prefix), '{}/merge'.format(url_prefix))