Add progress support for bulk deletion

plus bulk-delete all tempmon readings when deleting client or probe
This commit is contained in:
Lance Edgar 2017-08-04 16:11:45 -05:00
parent d8be651e95
commit 3205d61ba6
5 changed files with 88 additions and 10 deletions

View file

@ -32,9 +32,11 @@ from sqlalchemy import orm
import sqlalchemy_continuum as continuum
from rattail.db import Session as RattailSession
from rattail.db.continuum import model_transaction_query
from rattail.util import prettify
from rattail.time import localtime
from rattail.threads import Thread
import formalchemy as fa
from pyramid import httpexceptions
@ -43,6 +45,7 @@ from webhelpers2.html import HTML, tags
from tailbone import forms, grids
from tailbone.views import View
from tailbone.progress import SessionProgress
class MasterView(View):
@ -702,20 +705,60 @@ class MasterView(View):
Delete all records matching the current grid query
"""
if self.request.method == 'POST':
query = self.get_effective_query(sortable=False)
count = query.count()
self.bulk_delete_objects(query)
self.request.session.flash("Deleted {:,d} {}".format(count, self.get_model_title_plural()))
key = '{}.bulk_delete'.format(self.model_class.__tablename__)
objects = self.get_effective_data()
progress = SessionProgress(self.request, key)
thread = Thread(target=self.bulk_delete_thread, args=(objects, progress))
thread.start()
return self.render_progress({
'key': key,
'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())
def bulk_delete_objects(self, query):
# TODO: sometimes the first makes sense, and would be preferred for
# efficiency's sake. might even need to add progress to latter?
# query.delete(synchronize_session=False)
for obj in query:
self.Session.delete(obj)
def bulk_delete_objects(self, session, objects, progress=None):
def delete(obj, i):
session.delete(obj)
self.progress_loop(delete, objects, progress,
message="Deleting objects")
def get_bulk_delete_session(self):
return RattailSession()
def bulk_delete_thread(self, objects, progress):
"""
Thread target for bulk-deleting current results, with progress.
"""
session = self.get_bulk_delete_session()
objects = objects.with_session(session).all()
try:
self.bulk_delete_objects(session, objects, progress=progress)
# If anything goes wrong, rollback and log the error etc.
except Exception as error:
session.rollback()
log.exception("execution failed for batch results")
session.close()
if progress:
progress.session.load()
progress.session['error'] = True
progress.session['error_msg'] = "Bulk deletion failed: {}: {}".format(type(error).__name__, error)
progress.session.save()
# If no error, check result flag (false means user canceled).
else:
session.commit()
session.close()
if progress:
progress.session.load()
progress.session['complete'] = True
progress.session['success_url'] = self.get_index_url()
progress.session.save()
def get_merge_fields(self):
if hasattr(self, 'merge_fields'):