backoffice: export formdata in an afterjob if there are too many items (#1591)

This commit is contained in:
Frédéric Péters 2012-10-02 11:26:13 +02:00
parent 71ecb4b2cc
commit fb54638215
1 changed files with 120 additions and 28 deletions

View File

@ -26,8 +26,9 @@ from qommon.backoffice import BackofficeRootDirectory
from qommon.backoffice.menu import html_top
from qommon import misc, get_logger
from qommon.afterjobs import AfterJob
from qommon import errors
from wcs.forms.common import FormStatusPage
from wcs.categories import Category
@ -168,7 +169,7 @@ class FakeField:
return [element]
class FormPage(Directory):
_q_exports = ['', 'csv', 'stats', 'xls', 'pending']
_q_exports = ['', 'csv', 'stats', 'xls', 'pending', 'export']
def __init__(self, component):
try:
@ -356,52 +357,143 @@ class FormPage(Directory):
return elements
def csv(self):
get_logger().info('backoffice - form %s - listing csv' % self.formdef.name)
fields = self.get_fields_from_query()
selected_filter = self.get_filter_from_query()
output = cStringIO.StringIO()
csv_output = csv.writer(output)
class Exporter:
def __init__(self, formpage, formdef, fields, selected_filter):
self.formpage = formpage
self.formdef = formdef
self.fields = fields
self.selected_filter = selected_filter
csv_output.writerow(self.csv_tuple_heading(fields))
def export(self, job=None):
self.output = cStringIO.StringIO()
csv_output = csv.writer(self.output)
items, total_count = FormDefUI(self.formdef).get_listing_items(selected_filter)
csv_output.writerow(self.formpage.csv_tuple_heading(self.fields))
for filled in items:
csv_output.writerow(self.csv_tuple(fields, filled))
items, total_count = FormDefUI(self.formdef).get_listing_items(self.selected_filter)
for filled in items:
csv_output.writerow(self.formpage.csv_tuple(self.fields, filled))
if job:
job.file_content = self.output.getvalue()
job.content_type = 'text/csv'
job.file_name = '%s.csv' % self.formdef.url_name
job.store()
get_logger().info('backoffice - form %s - listing csv' % self.formdef.name)
count = self.formdef.data_class().count()
exporter = Exporter(self, self.formdef, fields, selected_filter)
if count > 100: # Arbitrary threshold
job = get_response().add_after_job(
str(N_('Exporting forms in CSV')),
exporter.export)
return redirect('export?job=%s' % job.id)
else:
exporter.export()
response = get_response()
response.set_content_type('text/csv')
response.set_header('content-disposition', 'attachment; filename=%s.csv' % self.formdef.url_name)
return exporter.output.getvalue()
def export [html] (self):
if get_request().form.get('download'):
return self.export_download()
try:
job = AfterJob.get(get_request().form.get('job'))
except KeyError:
return redirect('.')
html_top('forms', title=_('Exporting'))
get_session().display_message()
get_response().add_javascript(['jquery.js', 'interface.js', 'afterjob.js'])
'<dl class="job-status">'
'<dt>'
_(job.label)
'</dt>'
'<dd>'
'<span class="afterjob" id="%s">' % job.id
_(job.status)
'</span>'
'</dd>'
'</dl>'
'<div class="done">'
'<a href="export?download=%s">%s</a>' % (job.id, _('Download Export'))
'</div>'
def export_download(self):
try:
job = AfterJob.get(get_request().form.get('download'))
except KeyError:
return redirect('.')
if not job.status == 'completed':
raise TraversalError()
response = get_response()
response.set_content_type('text/csv')
response.set_header('content-disposition', 'attachment; filename=export.csv')
return output.getvalue()
response.set_content_type(job.content_type)
response.set_header('content-disposition',
'attachment; filename=%s' % job.file_name)
return job.file_content
def xls(self):
if xlwt is None:
raise errors.TraversalError()
get_logger().info('backoffice - form %s - as excel' % self.formdef.name)
fields = self.get_fields_from_query()
selected_filter = self.get_filter_from_query()
w = xlwt.Workbook(encoding=get_publisher().site_charset)
ws = w.add_sheet('1')
class Exporter:
def __init__(self, formpage, formdef, fields, selected_filter):
self.formpage = formpage
self.formdef = formdef
self.fields = fields
self.selected_filter = selected_filter
for i, f in enumerate(self.csv_tuple_heading(fields)):
ws.write(0, i, f)
def export(self, job=None):
w = xlwt.Workbook(encoding=get_publisher().site_charset)
ws = w.add_sheet('1')
items, total_count = FormDefUI(self.formdef).get_listing_items(selected_filter)
for i, f in enumerate(self.formpage.csv_tuple_heading(self.fields)):
ws.write(0, i, f)
for i, filled in enumerate(items):
for j, elem in enumerate(self.csv_tuple(fields, filled)):
ws.write(i+1, j, elem)
items, total_count = FormDefUI(self.formdef).get_listing_items(self.selected_filter)
output = cStringIO.StringIO()
w.save(output)
for i, filled in enumerate(items):
for j, elem in enumerate(self.formpage.csv_tuple(fields, filled)):
ws.write(i+1, j, elem)
response = get_response()
response.set_content_type('application/vnd.ms-excel')
response.set_header('content-disposition', 'attachment; filename=export.xls')
return output.getvalue()
self.output = cStringIO.StringIO()
w.save(self.output)
if job:
job.file_content = self.output.getvalue()
job.content_type = 'application/vnd.ms-excel'
job.file_name = '%s.xls' % self.formdef.url_name
job.store()
get_logger().info('backoffice - form %s - as excel' % self.formdef.name)
count = self.formdef.data_class().count()
exporter = Exporter(self, self.formdef, fields, selected_filter)
if count > 100: # Arbitrary threshold
job = get_response().add_after_job(
str(N_('Exporting forms in Excel format')),
exporter.export)
return redirect('export?job=%s' % job.id)
else:
exporter.export()
response = get_response()
response.set_content_type('application/vnd.ms-excel')
response.set_header('content-disposition', 'attachment; filename=%s.xls' % self.formdef.url_name)
return exporter.output.getvalue()
def stats [html] (self):
get_logger().info('backoffice - form %s - stats' % self.formdef.name)