import datetime from django.db.models.query import QuerySet , ValuesQuerySet from django.http import HttpResponse class ExcelResponse ( HttpResponse ): def __init__ ( self , data , output_name = 'excel_data' , headers = None , force_csv = False , encoding = 'utf8' ): # Make sure we've got the right type of data to work with valid_data = False if isinstance ( data , ValuesQuerySet ): data = list ( data ) elif isinstance ( data , QuerySet ): data = list ( data . values ()) 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 : # xlwt doesn't exist; fall back to csv pass else : use_xls = True if use_xls : book = xlwt . Workbook ( encoding = encoding ) sheet = book . add_sheet ( 'Sheet 1' ) 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' : 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 "

' % '","' . 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 ( '"' , ' \" ' ), file_ext )