forked from CGM_Public/pretix_original
Add MultiSheetListExporter base class
This commit is contained in:
@@ -5,7 +5,7 @@ from typing import Tuple
|
|||||||
|
|
||||||
from defusedcsv import csv
|
from defusedcsv import csv
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
from openpyxl.cell.cell import KNOWN_TYPES
|
from openpyxl.cell.cell import KNOWN_TYPES
|
||||||
|
|
||||||
@@ -143,3 +143,73 @@ class ListExporter(BaseExporter):
|
|||||||
return self._render_csv(form_data, dialect='excel')
|
return self._render_csv(form_data, dialect='excel')
|
||||||
elif form_data.get('_format') == 'semicolon':
|
elif form_data.get('_format') == 'semicolon':
|
||||||
return self._render_csv(form_data, dialect='excel', delimiter=';')
|
return self._render_csv(form_data, dialect='excel', delimiter=';')
|
||||||
|
|
||||||
|
|
||||||
|
class MultiSheetListExporter(ListExporter):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sheets(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def export_form_fields(self) -> dict:
|
||||||
|
choices = [
|
||||||
|
('xlsx', _('Excel (.xlsx)')),
|
||||||
|
]
|
||||||
|
for s, l in self.sheets:
|
||||||
|
choices += [
|
||||||
|
(s + ':default', str(l) + ' – ' + ugettext('CSV (with commas)')),
|
||||||
|
(s + ':excel', str(l) + ' – ' + ugettext('CSV (Excel-style)')),
|
||||||
|
(s + ':semicolon', str(l) + ' – ' + ugettext('CSV (with semicolons)')),
|
||||||
|
]
|
||||||
|
ff = OrderedDict(
|
||||||
|
[
|
||||||
|
('_format',
|
||||||
|
forms.ChoiceField(
|
||||||
|
label=_('Export format'),
|
||||||
|
choices=choices,
|
||||||
|
)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
ff.update(self.additional_form_fields)
|
||||||
|
return ff
|
||||||
|
|
||||||
|
def iterate_list(self, form_data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def iterate_sheet(self, form_data, sheet):
|
||||||
|
raise NotImplementedError() # noqa
|
||||||
|
|
||||||
|
def _render_sheet_csv(self, form_data, sheet, **kwargs):
|
||||||
|
output = io.StringIO()
|
||||||
|
writer = csv.writer(output, **kwargs)
|
||||||
|
for line in self.iterate_sheet(form_data, sheet):
|
||||||
|
writer.writerow(line)
|
||||||
|
return self.get_filename() + '.csv', 'text/csv', output.getvalue().encode("utf-8")
|
||||||
|
|
||||||
|
def _render_xlsx(self, form_data):
|
||||||
|
wb = Workbook()
|
||||||
|
ws = wb.get_active_sheet()
|
||||||
|
wb.remove(ws)
|
||||||
|
for s, l in self.sheets:
|
||||||
|
ws = wb.create_sheet(str(l))
|
||||||
|
for i, line in enumerate(self.iterate_sheet(form_data, sheet=s)):
|
||||||
|
for j, val in enumerate(line):
|
||||||
|
ws.cell(row=i + 1, column=j + 1).value = str(val) if not isinstance(val, KNOWN_TYPES) else val
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile(suffix='.xlsx') as f:
|
||||||
|
wb.save(f.name)
|
||||||
|
f.seek(0)
|
||||||
|
return self.get_filename() + '.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', f.read()
|
||||||
|
|
||||||
|
def render(self, form_data: dict) -> Tuple[str, str, bytes]:
|
||||||
|
if form_data.get('_format') == 'xlsx':
|
||||||
|
return self._render_xlsx(form_data)
|
||||||
|
elif ':' in form_data.get('_format'):
|
||||||
|
sheet, f = form_data.get('_format').split(':')
|
||||||
|
if f == 'default':
|
||||||
|
return self._render_sheet_csv(form_data, sheet, quoting=csv.QUOTE_NONNUMERIC, delimiter=',')
|
||||||
|
elif f == 'csv-excel':
|
||||||
|
return self._render_sheet_csv(form_data, sheet, dialect='excel')
|
||||||
|
elif f == 'semicolon':
|
||||||
|
return self._render_sheet_csv(form_data, sheet, dialect='excel', delimiter=';')
|
||||||
|
|||||||
Reference in New Issue
Block a user