Django文件导出excel文件和打包zip导出--包括文件字符流导出下载

首先说说我对文件导出下载的看法(思路):
1、浅短的认知
需求:把数据库中的数据导出到excel中,支持下载,
逻辑:1)把数据库中的数据存放到excel文件中,excel文件放到数据库中的目录中,
	 2)把文件所在路径拼接成url返还给前端页面,
	 3)前端页面请求此url路径,浏览器自动下载excel文件,

上述方法总结:
上面的方法确实能够做到数据的导出,但是有一下几个问题:
1、服务器中会保留所生成的文件,虽然也可以定时删除,但是对服务器进行了多次的IO操作,不是很推荐,但是如果需要保留用户导出了那些数据,就可以分析用户的行为,则此方法就很完美。
2、对于此方法还有个优点,可以避免重复的把数据进行导入到excel文件中,保存对应的查询条件,用来对应所生成的excel文件,第二次或者多次导出相同的数据就可以把excel文件直接给用户下载。
3、如果对于生成的文件没有作用,那么上述的方法就会导致服务器进行了多次IO操作,增加服务器压力。

2、深入一点的认知

在经过大佬的指点后,发现了另一种导出excel文件的方法,不用在服务器中生成excel文件,直接通过浏览器下载,把文件以流的方式给浏览器,就会自动下载。

话不多说看代码:
环境:Python 2.7、django 1.9

class TeseExeclView(View):
    def get(self,request):
        """
        导出excel表格
        """
        list_obj = AccountChatInfo.objects.values('send_account','receive_account','content').order_by("-send_at")[:30000]
        if list_obj:
            # 创建工作薄
            ws = Workbook(encoding='utf-8')
            w = ws.add_sheet(u"数据报表第一页")
            w.write(0, 0, u"发送帐号")
            w.write(0, 1, u"接收帐号")
            w.write(0, 2, u"内容")

            # 写入数据
            excel_row = 1
            for obj in list_obj:
                send = obj['send_account']
                receive = obj['receive_account']
                data_content = obj['content']
                w.write(excel_row, 0, send)
                w.write(excel_row, 1, receive)
                w.write(excel_row, 2, data_content)
                excel_row += 1
            sio = StringIO.StringIO()
            ws.save(sio)
            sio.seek(0)
            response = HttpResponse(sio.getvalue(), content_type='application/vnd.ms-excel')
            response['Content-Disposition'] = 'attachment; filename=test.xls'
            # 将文件流写入到response返回
            response.write(sio.getvalue())
            return response
        else:
            return JsonResponse('no data')

excel文件打包zip导出

这个目前没找到把excel文件流放到zip文件流中的方法,所以只能通过在服务器上生成文件来进行导出。
仅供参考-记得把文件路径修改成自己的

class TestExcelView(View):
    '''excel导出'''
    excel_title = [u'发送帐号', u'接收帐号', u'内容']

    def excel_method(self, list_obj, file_dir_name):
		'''生成每个excel文件的方法'''
        # 创建工作薄
        ws = Workbook(encoding='utf-8')
        sheet_num = 1
        w = ws.add_sheet(u"sheet" + str(sheet_num))
        # excel表格第一行字段信息
        for i, m in enumerate(self.excel_title):
            w.write(0, i, m)

        # 写入数据
        excel_row = 1  # 记录行号
        for obj in list_obj:
            send = obj['send_account']
            receive = obj['receive_account']
            data_content = obj['content']
            w.write(excel_row, 0, send)
            w.write(excel_row, 1, receive)
            w.write(excel_row, 2, data_content)
            excel_row += 1
            # excel最大行为65536,所以换第二个工作表写
            if excel_row == 65536:
                excel_row = 1
                sheet_num += 1
                w = ws.add_sheet(u"sheet" + str(sheet_num))
                for i, m in enumerate(self.excel_title):
                    w.write(0, i, m)
        # todo 你存要放文件的文件夹路径,记得修改成自己的
        path = '../static/excel/'
        # 路径不存在,就创建
        if not os.path.exists(path):
            os.makedirs(path)
        file_name = file_dir_name + '.xls'
        ws.save(path + file_name)
        # 返回文件名
        return file_name


    def get(self,request):   
        try:
        	obj = AccountChatInfo.objects.values('send_account','receive_account','content').order_by("-send_at")
            obj_count = obj.count()
            print u'总数据量-', obj_count
            excel_number = 300000   # 30万条数据一个excel文件
            if obj_count:
                excel_file_list = []   # excel文件列表
                file_pageobj = []
                # 计算总数据量能够导出多少个excel文件
                if obj_count > excel_number:
                    file_num = obj_count // excel_number
                    remainder = obj_count % excel_number
                    if remainder != 0:
                        file_num = file_num + 1
                    for index in range(0, file_num):
                        if index == file_num - 1:
                            file_pageobj.append(list_obj[index * excel_number:])
                        else:
                            file_pageobj.append(list_obj[index * excel_number:(index + 1) * excel_number])
                else:
                    file_pageobj = [list_obj]
                file_dir_name = str(int(time.time()))
                for index, i in enumerate(file_pageobj):
                    # 文件名取时间戳+下划线+编号
                    one_excel_name = file_dir_name + '_' + str(index)
                    # t1 = time.time()
                    try:
                        file_name = self.excel_method(i, one_excel_name)
                    except:
                        continue
                    # print time.time() - t1
                    excel_file_list.append(file_name)

                # todo 你存要放文件的文件夹路径,记得修改成自己的
        		path = '../static/excel/'
                with zipfile.ZipFile(path + '{}.zip'.format(file_dir_name), mode='w') as zf:
                    for m in excel_file_list:
                        if os.path.exists(path + m):
                            zf.write(path + m, os.path.basename(m))
                            # 删除保留的exccel文件
                            os.remove(path + m)
                url = 'http://' + request.META['HTTP_HOST'] + '/static/excel/' + '{}.zip'.format(file_dir_name)
                # print u'总时间--', time.time() - time1
                return JsonResponse({'status': True, 'url': url})
            else:
                return JsonResponse({'status': False, 'url': '', 'msg': u'数据为空!'})
        except Exception as e:
            print e
            return JsonResponse({'status': False, 'url': '', 'msg': u'导出失败!'})

如有不足恳请各位大佬指点–会更新,

参考–:https://blog.csdn.net/gezi_/article/details/77319688

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值