python通过指定excel模板导出_Django项目实现指定生成excel并导出本地功能

博客原创,作者:BruceBee,转载请标明出处,谢谢!

最近在用django写一个项目,项目当中有一处功能,需要在前端进行数据的选择,然后生成对应的excel表格并进行下载到本地。

将此功能进行拆解:

一、前端进行内容选择,生成excel表格

二、后端生成的excle表格供前端进行下载

python中提供的xlwt模块即可以实现生成excel表格,前后端的信息交互采用ajax,文件下载采用web前端访问url形式实现。

一、后端生成excel

现在我的项目目录下新建一个download目录,用于存储download的py文件和生成的excel文件,其中FileHandle.py为处理excel的主函数。

[root@localhost download]#tree

.

├── core

│?? ├── FileHandle.py

│?? ├── FileHandle.pyc

│?? ├──__init__.py

│?? └──__init__.pyc

├── file

│?? ├── csv

│?? └── excel

├──__init__.py

└──__init__.pyc

View Code

FileHandle.py:

1 #-*- coding:utf-8 -*-

2 importos,django,sys3 BASE_DIR =os.path.dirname(os.path.dirname(os.path.abspath(__file__)))4 sys.path.append(BASE_DIR)5

6 from Log.models importActionLog,SSHLog7 from OM.models importServerGroup,ServerList8 from Matrix.models importBaseInfo,ConfigInfo,Platform,BusinessUnit,DomainInfo,DnsInfo,ZabbixAlertInfo,Asset9

10 importdatetime11 importxlwt12

13

14 defBulidNewExcel(download_url,dbname):15 db_dict={16 'BaseInfo':BaseInfo,17 'ConfigInfo':ConfigInfo,18 'Platform':Platform,19 'BusinessUnit':BusinessUnit,20 'DomainInfo':DomainInfo,21 'DnsInfo':DnsInfo,22 'ZabbixAlertInfo':ZabbixAlertInfo,23 'Asset':Asset,24 'ActionLog':ActionLog,25 'SSHLog':SSHLog,26 'ServerGroup':ServerGroup,27 'ServerList':ServerList,28 }29 style0 = xlwt.easyxf('font: name Times New Roman, color-index red, bold on')30 style1 = xlwt.easyxf(num_format_str='D-MMM-YY')31 #获取字段名(列表)

32 field_name_list =[]33 field_verbose_name_list =[]34

35 #for i in models.SSHLog._meta.get_fields():

36 for i indb_dict[dbname]._meta.get_fields():37 field_name_list.append(i.name)38 if db_dict[dbname] ==BaseInfo or db_dict[dbname] ==Platform or db_dict[dbname] ==BusinessUnit or db_dict[dbname] ==DomainInfo:39 field_verbose_name_list.append(i.name)40 else:41 field_verbose_name_list.append(i._verbose_name)42

43 #Dns表中字段替换

44 field_name_list = ['Domain_name_id' if x == 'Domain_name' else x for x infield_name_list]45 #config表中字段替换

46 field_name_list = ['baseid_id' if x == 'baseid' else x for x infield_name_list]47

48 #plat、buss表字段替换

49 if 'baseinfo' in field_name_list:field_name_list.remove('baseinfo')50 if 'baseinfo' in field_verbose_name_list:field_verbose_name_list.remove('baseinfo')51 #domain表字段替换

52 if 'dnsinfo' in field_name_list:field_name_list.remove('dnsinfo')53 if 'dnsinfo' in field_verbose_name_list:field_verbose_name_list.remove('dnsinfo')54

55 #base表字段替换

56 if 'configinfo' in field_name_list:field_name_list.remove('configinfo')57 if 'business_unit' in field_name_list:field_name_list.remove('business_unit')58 if 'configinfo' in field_verbose_name_list:field_verbose_name_list.remove('configinfo')59 if 'business_unit' in field_verbose_name_list:field_verbose_name_list.remove('business_unit')60

61 field_name_list = ['isp_id' if x == 'isp' else x for x infield_name_list]62

63

64 style0 = xlwt.easyxf('font: name Times New Roman, color-index red, bold on')65 style1 = xlwt.easyxf(num_format_str='D-MMM-YY')66

67 wb =xlwt.Workbook()68 ws = wb.add_sheet('Sheet',cell_overwrite_ok=True)69 for i inrange(len(field_verbose_name_list)):70 ws.write(0,i,field_verbose_name_list[i],style0)71

72 mylist=[]73

74 log_obj =db_dict[dbname].objects.all()75

76

77 num =078 for i inlog_obj.values():79 mylist.append([])80 for j inrange(len(field_name_list)):81 mylist[num].append(i[field_name_list[j]])82 num+=1

83

84 for i inrange(0,log_obj.count()):85 for j inrange(len(field_verbose_name_list)):86 ws.write(i+1,j,mylist[i][j])87 timestr=datetime.datetime.now().strftime("%Y%m%d%H%M%S")88 wb.save(download_url+'New-'+timestr+'.xls')89 return timestr

View Code

说明如下:

2-4行:BASE_DIR为获取问文件路径,并将其添加到django的包路径中,供django的app调用;

6-8行:项目本地的models里面的名称,,由于我有三个app,为避免混淆我分别导入。可根据自己的情况修改;

14行:传入2个参数,分别为我定义好的文件存储路径和需要对应的数据库名称;

15-28行:定义字符串与实际数据库名为k-v关系的字典;

32-33行:定义两个列表,目的是将从models中获取的models的字段名和字段中文名提取出来(name与verbose_name),这里需要注意的是:如果你的models关系里没有定义verbose_name,那么提取出来的verbose_name将为空,多对多关系的字段没有verbose_name属性,直接取的话会报错;

36-61行:本项目实际情况对两个列表进行的处置动作,目的是得到最终的表格头部的内容,可忽略;

64-70行:实例化一个表格对象,使表格支持重复覆盖(即写动作),将列表内容写入表格的第一行,即得到表头。

74行:提取对应modles的内容,得到一个QuerySet对象,遍历这个对象,每个key就是一个记录,以字典形式呈现;

78-82行:嵌套循环,目的是生成一个列表,由每一条字段值组成的小列表,这些小列表为元素,组成一个大列表;

84-86行:嵌套循环这个大列表,将列表中的值写入到表格对象中;

87-89行:生成时间,将excel表格命名为New-‘时间格式’.xls,保存,返回该时间格式字符串;

至此,excel文件生成完成,但是潜在一个问题:就是当需要生成的数据量足够大的时候,这个转换列表也就足够大,其占用内存必然会很大。

view.py

1 from download.core importFileHandle2 defBulidData(request):3 dbname = request.POST.get('dbname')4 #return HttpResponse(dbname)

5 ret = FileHandle.BulidNewExcel('/var/www/html/dtop/download/file/excel/',dbname)6 returnHttpResponse(ret)7

8

9 defdownload(request,offset):10 #ret = FileHandle.BulidNewExcel('/var/www/html/dtop/download/file/excel/')

11 from django.http importStreamingHttpResponse12 def file_iterator(file_name,chunk_size=512):13 with open(file_name) as f:14 whileTrue:15 c =f.read(chunk_size)16 ifc:17 yieldc18 else:19 break

20

21 the_file_name ='New-'+offset+'.xls'

22 response = StreamingHttpResponse(file_iterator('/var/www/html/dtop/download/file/excel/New-'+offset+'.xls'))23 response['Content-Type'] = 'application/octet-stream'

24 response['Content-Disposition'] = 'attachment;filename="{0}"'.format(the_file_name)25

26 return response

View Code

说明如下:

1行:从前面的download目录中导入表格生成函数

2-7行:BulidData函数调用生成表格,得到该表格名称的时间字符串

9-26行:download函数根据用户传进来的offset值,拼接成文件名称字符串,并到指定目录取回该文件,以http流方式返回给前端,即实际的下载功能。

url.py:

urlpatterns =[

url(r'^BulidData/', Matrix.views.BulidData),

url(r'^download/(\w+)*/$', Matrix.views.download),

]

View Code

说明如下:

在url里添加以上两个函数的路由信息;注意download函数采用动态url的方式获取用户的参数,这里参数实际上是一串日期字符串,即前面的Filehadle函数返回的timestr

二:前端交互并下载

html界面:

View Code

说明如下:为了简化,我只写了一个button,注意这里的name属性值最终是要传递给后端,与FileHadel函数里的字典进行匹配,需要取不同数据库的excel,改这里就可以了。

js:

1 functiondownData(){2 var inputChecks=$("input:checkbox[name='dataFrom_check']:checked");3 if(inputChecks.length==0){4 layer.alert('请选中导出项!');5 return;6 }7 var dbname =$("#downData").attr("name")8

9 $.ajax({10 type:'POST',11 url:'/BulidData/',12 dataType:'text',13 data:{'dbname':dbname},14 success:function(text){15 var url ='/download/'+text;16 window.location.href=url;17 },error:function(){18 alert('导出失败');19 }20 });21

22 }

View Code

说明如下:

定义了一个downData函数,获取指定DOM元素的的name属性,通过ajax传递给BulidData函数,生成excel,得到该excel文件时间字符串

16行:window.location.href=url,ajax访问该url,即实际的下载功能。

至此,前端点击“导出”按钮,即可实现后端生成excel并下载只本地,功能实现。但是这个功能还有一些地方不完善,除了前面提到的转换形成的列表是个潜在的因素以外(后来测试了一下,生成一个8000条的excel表格,内存2G的虚拟机mysql瞬时的占用内存才不到10%,CPU使用率不到5%,从前端点击到下载到本地,感觉耗时不到半秒钟)。自定义内容的excel表格没有实现,后续自己慢慢完善该功能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值