# -*- coding: utf-8 -*- """ExcelResponse for emencia.django.newsletter""" # Based on http://www.djangosnippets.org/snippets/1151/ import datetime from django.http import HttpResponse from django.db.models.query import QuerySet from django.db.models.query import ValuesQuerySet # from ..models import ContactSettings from collections import OrderedDict from functions.translate import fill_trans_fields_r from theme.models import Theme class ExcelResponse(HttpResponse): """ExcelResponse feeded by queryset""" def __init__(self, data, output_name='excel_data', headers=None, sheet_name = "Sheet1", default_style=None, force_csv=False, encoding='utf8'): valid_data = False qs = data.prefetch_related('contactsettings', 'contactsettings__theme', 'contactsettings__area') # if isinstance(data, ValuesQuerySet): # data = list(data) # elif isinstance(data, QuerySet): # data = list(data.values()) # print(data) # if 'settings' in headers: data = [] themes = dict(Theme.objects.language('ru').all().values_list('pk', 'name')) for item in qs: data.append([ item.email, item.first_name, item.contactsettings.exponent_practicum, item.contactsettings.organiser_practicum, item.creation_date.strftime('%d.%m.%Y'), item.modification_date.strftime('%d.%m.%Y'), ', '.join([getattr(fill_trans_fields_r(obj=x, lang='ru'), 'name', '') for x in item.contactsettings.area.all()]), ', '.join([themes.get(x.pk) for x in item.contactsettings.theme.all()]), ]) headers = ('email', 'first_name', 'приактикум экспонента', 'практикум организатор', 'дата подписки', 'дата изменения', 'гео', 'темы') # if hasattr(data, '__getitem__'): # if isinstance(data[0], dict): # if headers is None: # headers = data[0].keys() # data = [[row[col] for col in headers] for row in data] data.insert(0, headers) # if hasattr(data[0], '__getitem__'): # valid_data = True # assert valid_data is True, "ExcelResponse requires a sequence of sequences" import StringIO output = StringIO.StringIO() # Excel has a limit on number of rows; if we have more than that, make a csv use_xls = False if len(data) <= 65536 and force_csv is not True: try: import xlwt except ImportError: pass else: use_xls = True if use_xls: book = xlwt.Workbook(encoding=encoding) sheet = book.add_sheet(sheet_name) styles = {'datetime': xlwt.easyxf(num_format_str='yyyy-mm-dd hh:mm:ss'), 'date': xlwt.easyxf(num_format_str='yyyy-mm-dd'), 'time': xlwt.easyxf(num_format_str='hh:mm:ss'), 'default': default_style or xlwt.Style.default_style} for rowx, row in enumerate(data): for colx, value in enumerate(row): if isinstance(value, datetime.datetime): cell_style = styles['datetime'] elif isinstance(value, datetime.date): cell_style = styles['date'] elif isinstance(value, datetime.time): cell_style = styles['time'] else: cell_style = styles['default'] sheet.write(rowx, colx, value, style=cell_style) book.save(output) mimetype = 'application/vnd.ms-excel' file_ext = 'xls' else: for row in data: out_row = [] for value in row: if not isinstance(value, basestring): value = unicode(value) value = value.encode(encoding) out_row.append(value.replace('"', '""')) output.write('"%s"\n' % '","'.join(out_row)) mimetype = 'text/csv' file_ext = 'csv' output.seek(0) super(ExcelResponse, self).__init__(content=output.getvalue(), mimetype=mimetype) self['Content-Disposition'] = 'attachment;filename="%s.%s"' % \ (output_name.replace('"', '\"')[:27], file_ext)