Add support for downloading batch rows as XLSX file
This commit is contained in:
parent
10c30cd21a
commit
6cfc72c875
|
@ -67,6 +67,9 @@
|
||||||
% if master.has_rows and master.rows_downloadable_csv and request.has_perm('{}.row_results_csv'.format(permission_prefix)):
|
% if master.has_rows and master.rows_downloadable_csv and request.has_perm('{}.row_results_csv'.format(permission_prefix)):
|
||||||
<li>${h.link_to("Download row results as CSV", url('{}.row_results_csv'.format(route_prefix), uuid=instance.uuid))}</li>
|
<li>${h.link_to("Download row results as CSV", url('{}.row_results_csv'.format(route_prefix), uuid=instance.uuid))}</li>
|
||||||
% endif
|
% endif
|
||||||
|
% if master.has_rows and master.rows_downloadable_xlsx and request.has_perm('{}.row_results_xlsx'.format(permission_prefix)):
|
||||||
|
<li>${h.link_to("Download row results as XLSX", url('{}.row_results_xlsx'.format(route_prefix), uuid=instance.uuid))}</li>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="object_helpers()"></%def>
|
<%def name="object_helpers()"></%def>
|
||||||
|
|
|
@ -74,6 +74,7 @@ class BatchMasterView(MasterView):
|
||||||
has_rows = True
|
has_rows = True
|
||||||
rows_deletable = True
|
rows_deletable = True
|
||||||
rows_downloadable_csv = True
|
rows_downloadable_csv = True
|
||||||
|
rows_downloadable_xlsx = True
|
||||||
refreshable = True
|
refreshable = True
|
||||||
refresh_after_create = False
|
refresh_after_create = False
|
||||||
cloneable = False
|
cloneable = False
|
||||||
|
@ -1333,6 +1334,9 @@ class BatchMasterView(MasterView):
|
||||||
def get_row_results_csv_filename(self, batch):
|
def get_row_results_csv_filename(self, batch):
|
||||||
return '{}.{}.csv'.format(self.get_route_prefix(), batch.id_str)
|
return '{}.{}.csv'.format(self.get_route_prefix(), batch.id_str)
|
||||||
|
|
||||||
|
def get_row_results_xlsx_filename(self, batch):
|
||||||
|
return '{}.{}.xlsx'.format(self.get_route_prefix(), batch.id_str)
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
"""
|
"""
|
||||||
Clone current batch as new batch
|
Clone current batch as new batch
|
||||||
|
|
|
@ -45,6 +45,7 @@ from rattail.threads import Thread
|
||||||
from rattail.csvutil import UnicodeDictWriter
|
from rattail.csvutil import UnicodeDictWriter
|
||||||
from rattail.files import temp_path
|
from rattail.files import temp_path
|
||||||
from rattail.excel import ExcelWriter
|
from rattail.excel import ExcelWriter
|
||||||
|
from rattail.gpc import GPC
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
import deform
|
import deform
|
||||||
|
@ -141,6 +142,7 @@ class MasterView(View):
|
||||||
rows_bulk_deletable = False
|
rows_bulk_deletable = False
|
||||||
rows_default_pagesize = 20
|
rows_default_pagesize = 20
|
||||||
rows_downloadable_csv = False
|
rows_downloadable_csv = False
|
||||||
|
rows_downloadable_xlsx = False
|
||||||
|
|
||||||
mobile_rows_creatable = False
|
mobile_rows_creatable = False
|
||||||
mobile_rows_creatable_via_browse = False
|
mobile_rows_creatable_via_browse = False
|
||||||
|
@ -2354,6 +2356,64 @@ class MasterView(View):
|
||||||
row[field] = getattr(obj, field, None)
|
row[field] = getattr(obj, field, None)
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
def row_results_xlsx(self):
|
||||||
|
"""
|
||||||
|
Download current *row* results as XLSX.
|
||||||
|
"""
|
||||||
|
obj = self.get_instance()
|
||||||
|
results = self.get_effective_row_data(sort=True)
|
||||||
|
fields = self.get_row_xlsx_fields()
|
||||||
|
path = temp_path(suffix='.xlsx')
|
||||||
|
writer = ExcelWriter(path, fields, sheet_title=self.get_row_model_title_plural())
|
||||||
|
writer.write_header()
|
||||||
|
|
||||||
|
rows = []
|
||||||
|
for row_obj in results:
|
||||||
|
data = self.get_row_xlsx_row(row_obj, fields)
|
||||||
|
row = [data[field] for field in fields]
|
||||||
|
rows.append(row)
|
||||||
|
|
||||||
|
writer.write_rows(rows)
|
||||||
|
writer.auto_freeze()
|
||||||
|
writer.auto_filter()
|
||||||
|
writer.auto_resize()
|
||||||
|
writer.save()
|
||||||
|
|
||||||
|
response = self.request.response
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
response.body = f.read()
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
response.content_length = len(response.body)
|
||||||
|
response.content_type = str('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||||
|
filename = self.get_row_results_xlsx_filename(obj)
|
||||||
|
response.content_disposition = str('attachment; filename={}'.format(filename))
|
||||||
|
return response
|
||||||
|
|
||||||
|
def get_row_xlsx_fields(self):
|
||||||
|
"""
|
||||||
|
Return the list of row fields to be written to XLSX download.
|
||||||
|
"""
|
||||||
|
# TODO: should this be shared at all? in a better way?
|
||||||
|
return self.get_row_csv_fields()
|
||||||
|
|
||||||
|
def get_row_xlsx_row(self, row, fields):
|
||||||
|
"""
|
||||||
|
Return a dict for use when writing the row's data to XLSX download.
|
||||||
|
"""
|
||||||
|
xlrow = {}
|
||||||
|
for field in fields:
|
||||||
|
value = getattr(row, field, None)
|
||||||
|
|
||||||
|
if isinstance(value, GPC):
|
||||||
|
value = six.text_type(value)
|
||||||
|
|
||||||
|
xlrow[field] = value
|
||||||
|
return xlrow
|
||||||
|
|
||||||
|
def get_row_results_xlsx_filename(self, obj):
|
||||||
|
return '{}.xlsx'.format(self.get_row_grid_key())
|
||||||
|
|
||||||
def row_results_csv(self):
|
def row_results_csv(self):
|
||||||
"""
|
"""
|
||||||
Download current row results data for an object, as CSV
|
Download current row results data for an object, as CSV
|
||||||
|
@ -3265,6 +3325,14 @@ class MasterView(View):
|
||||||
config.add_view(cls, attr='row_results_csv', route_name='{}.row_results_csv'.format(route_prefix),
|
config.add_view(cls, attr='row_results_csv', route_name='{}.row_results_csv'.format(route_prefix),
|
||||||
permission='{}.row_results_csv'.format(permission_prefix))
|
permission='{}.row_results_csv'.format(permission_prefix))
|
||||||
|
|
||||||
|
# download row results as Excel
|
||||||
|
if cls.has_rows and cls.rows_downloadable_xlsx:
|
||||||
|
config.add_tailbone_permission(permission_prefix, '{}.row_results_xlsx'.format(permission_prefix),
|
||||||
|
"Download {} results as XLSX".format(row_model_title))
|
||||||
|
config.add_route('{}.row_results_xlsx'.format(route_prefix), '{}/{{uuid}}/rows-xlsx'.format(url_prefix))
|
||||||
|
config.add_view(cls, attr='row_results_xlsx', route_name='{}.row_results_xlsx'.format(route_prefix),
|
||||||
|
permission='{}.row_results_xlsx'.format(permission_prefix))
|
||||||
|
|
||||||
# create row
|
# create row
|
||||||
if cls.has_rows:
|
if cls.has_rows:
|
||||||
if cls.rows_creatable or cls.mobile_rows_creatable:
|
if cls.rows_creatable or cls.mobile_rows_creatable:
|
||||||
|
|
Loading…
Reference in a new issue