[每日一学] django ImportExportModelAdmin自定义导出数据
作者:精品下载站 日期:2020-09-23 00:00:00 浏览:80 分类:涨姿势
官方文档:django-import-export
django 导出数据到excel
借助官方文档的一些数据进行理解:
classAuthor(models.Model): name=models.CharField(max_length=100) def__str__(self): returnself.name classCategory(models.Model): name=models.CharField(max_length=100) def__str__(self): returnself.name classBook(models.Model): name=models.CharField('Bookname',max_length=100) author=models.ForeignKey(Author,blank=True,null=True) author_email=models.EmailField('Authoremail',max_length=75,blank=True) imported=models.BooleanField(default=False) published=models.DateField('Published',blank=True,null=True) price=models.DecimalField(max_digits=10,decimal_places=2,null=True,blank=True) categories=models.ManyToManyField(Category,blank=True) def__str__(self): returnself.name
创建导入或导出的资源
fromimport_exportimportresources fromcore.modelsimportBook classBookResource(resources.ModelResource): classMeta: model=Book #要影响哪些模型字段将包含在导入导出的资源中,请使用fields(自定义)选项将字段列入白名单 fields=('id','name','price',) #或将exclude(自定义)字段列入黑名单的选项 exclude=('imported',) #export_order(自定义)选项设置导出字段的显式顺序 export_order=('id','price','author','name')
现在已经创建了一个模型资源,我们可以导出到csv文件
>>>fromapp.adminimportBookResource >>>dataset=BookResource().export() >>>print(dataset.csv) id,name,author,author_email,imported,published,price,categories 2,Somebook,1,,0,2012-12-05,8.85,1
定义ModelResource字段时,可以遵循模型关系,
classBookResource(resources.ModelResource): classMeta: model=Book #注意这里是中间是两个下划线,表示链式调用的模型关系 fields=('author__name',)
定义ModelResource属性时,可以遵循模型关系,
fromimport_export.fieldsimportField classBookResource(resources.ModelResource): '''自定义属性时,attribute所对应的值可以是链式调用,author__name实际得到的就是作者的名字, 但是在查询时记得使用select_related(),以保证在查询时可以将所关联的外键数据一块查出,否则无法使用链式调用, 最下面会有完整的例子说明 ''' author_name=Field(attribute='author__name',column_name='作者名字') classMeta: model=Book # fields=() export_order=('id','price','author','name','author_name')
可以覆盖资源字段以更改其某些选项`
fromimport_export.fieldsimportField classBookResource(resources.ModelResource): published=Field(attribute='published',column_name='published_date') classMeta: model=Book
可以添加目标模型中不存在的其他字段
fromimport_export.fieldsimportField classBookResource(resources.ModelResource): myfield=Field(column_name='myfield',attribute='组织数据时自定义的名字') classMeta: model=Book
import_export.fields.Field可用的属性:
导出时进行高级数据处理:
''' 并非所有数据都可以从对象/模型属性中轻松提取。 为了在导出时将复杂的数据模型转换为(通常更简单)的已处理数据结构,dehydrate_<fieldname>应定义方法: ''' fromimport_export.fieldsimportField classBookResource(resources.ModelResource): full_title=Field() classMeta: model=Book defdehydrate_full_title(self,book): return'%sby%s'%(book.name,book.author.name)
在这种情况下,导出看起来像这样:
>>>fromapp.adminimportBookResource >>>dataset=BookResource().export() >>>print(dataset.csv) full_title,id,name,author,author_email,imported,published,price,categories Somebookby1,2,Somebook,1,,0,2012-12-05,8.85,1
自定义小部件
一个ModelResource创建与给定字段类型的默认控件的字段。如果小部件应使用不同的参数初始化,请设置widgets字典。
在此示例窗口小部件中,该published字段被覆盖以使用其他日期格式。此格式将同时用于导入和导出资源。
classBookResource(resources.ModelResource): classMeta: model=Book widgets={ 'published':{'format':'%d.%m.%Y'}, }
应用场景:
视图是这样的:
渲染上面的视图主要用到了两个表:观看表和分享表
classWatchStatistics(models.Model): """ 观看 """ #支持匿名用户 user=models.ForeignKey(User,null=True) course=models.ForeignKey(VideoInfo,related_name="watch_course") ip=models.CharField(max_length=31) duration=models.DecimalField(decimal_places=2,max_digits=12, default=0.00,null=True) createDate=models.DateTimeField(auto_now_add=True) enterprise=models.ForeignKey(Enterprise,related_name="watch_enterprise") startDate=models.DateTimeField() endDate=models.DateTimeField() type=models.CharField(max_length=50,choices=USER_TYPE_CHOICES,default=REGISTER_USER) classDistributionRelationship(models.Model): """ 分享 """ #受邀人 invited_user=models.ForeignKey(User,related_name='invited_user',null=True) #分享人 share_user=models.ForeignKey(User,related_name='share_user',null=True) course=models.ForeignKey("course.VideoInfo",related_name="relationship_course") createDate=models.DateTimeField(auto_now_add=True) updateDate=models.DateTimeField(auto_now=True)
难度就在于把两张表数据糅合在一块,并且还需要一些自定义的列,导出excel
后端代码:
fromimport_exportimportresources fromimport_exportimportfields from.modelsimportWatchStatistics classWatchStatisticsResource(resources.ModelResource): #attribute所对应的值,中间是两个下划线,链式调用 title=fields.Field(column_name='课程名称',attribute='course__title') user=fields.Field(column_name='用户',attribute='user__owner__name') tel=fields.Field(column_name='电话号码',attribute='user__owner__tel') view_count=fields.Field(column_name='访问次数',attribute='view_count') total_duration=fields.Field(column_name='累计观看时间(分钟)',attribute='total_view_time') endDate=fields.Field(column_name='最后观看时间',attribute='endDate') #share_user要对应到group_user.share_user share_user=fields.Field(column_name='分享人',attribute='share_user') classMeta: model=WatchStatistics fields=( ) export_order=('title','user','tel','view_count','total_duration','endDate','share_user') widgets={ 'endDate':{'format':'%Y-%m-%d%H:%M:%S'}, } @method_decorator(login_required,name='dispatch') classAdminExport(View): resource_model=None redirect_space=None model_class=None datetime_fields=[] search_fields=[] default_filters={} prefix="" default_order_sort_field=['id'] defexport(self,request,queryset): content_type=request.GET.get('content_type','application/vnd.ms-excel') dataset=self.resource_model().export(queryset=queryset) filename="%s_%s"%(self.prefix,utils.datetime2string()) if"excel"incontent_type: suffix="xls" elif"csv"incontent_type: suffix="csv" else: messages.error(request,u'导出格式有误!') logger.info("exportformaterror") returnredirect(self.redirect_space) content=getattr(dataset,suffix) ##content_type这里响应对象获得了一个特殊的mime类型,告诉浏览器这是个excel文件不是html response=HttpResponse(content,content_type=content_type) ##这里响应对象获得了附加的Content-Disposition协议头,它含有excel文件的名称,文件名随意,当浏览器访问它时,会以"另存为"对话框中使用它. response['Content-Disposition']='attachment;filename=%s'%( '{}.{}'.format(filename,suffix),) returnresponse classWatchStatisticsExport(AdminExport): resource_model=WatchStatisticsResource redirect_space='analysis:time' model_class=WatchStatistics prefix="watchstatistics" datetime_fields=[] search_fields=[] default_filters={} defget(self,request): course_id=self.request.GET.get('course_id') start_time=self.request.GET.get('start_time') end_time=self.request.GET.get('end_time') watchstatistics_list=WatchStatistics.objects.filter(course=course_id).select_related().order_by('-endDate') ifstart_time: watchstatistics_list=watchstatistics_list.filter(endDate__gte=start_time) ifend_time: watchstatistics_list=watchstatistics_list.filter(endDate__lte=end_time) #查询出当前课程的分享表 distribution_list=DistributionRelationship.objects.filter(course=course_id).select_related() invited_user_list=[] base_user=OrderedDict() forwatchinwatchstatistics_list: user=base_user.setdefault(watch.user_id,[]) user.insert(0,watch) #将分享表里受邀人的id所在记录append fordisindistribution_list: #将拥有受邀人的id记录在列表,加入多条的话,说明同一直播,此人被不同的人邀请进来或者分享人多次访问会造成多条记录 ifdis.invited_user.id==watch.user_id: user.append(dis) invited_user_list.append(watch.user_id) watch_records=[] foruser_id,usersinbase_user.items(): #判断如果有分享的记录,则excel加入邀请人 ifnotinvited_user_list: group_user=users[0] group_user.view_count=len(users) total_view_time=sum([u.durationforuinusers]) group_user.total_view_time=total_view_time watch_records.append(group_user) else: #判断如果学员与受邀人一致,则分开处理 group_user=users[0] ifgroup_user.user.idininvited_user_list: #同一个人在同一直播被多人邀请过,查找次数 num=invited_user_list.count(group_user.user.id) #减去分享记录和访问次数 group_user.view_count=len(users)-num total_view_time=sum([u.durationforuinusers[:-num]]) group_user.total_view_time=total_view_time share_user=users[-1].share_user.owner.name group_user.share_user=share_user else: group_user.view_count=len(users) total_view_time=sum([u.durationforuinusers]) group_user.total_view_time=total_view_time group_user.share_user='无' watch_records.append(group_user) returnself.export(request,queryset=watch_records)
效果如图:
猜你还喜欢
- 02-18 [驾车常识] 这3种违章务必15天内处理,否则或面临罚金翻倍?这是真的吗?
- 02-18 [驾车常识] 等红灯时前车出毛病不动了,后车实线变道被记3分?交警会如何判罚你知道吗?
- 02-18 [驾车常识] 高速上这些“新路标”80%的车主看不懂,你是其中的25%的人吗?
- 02-18 [涨姿势] 开车被追尾,若对方全责,记得多说这3句话,或能多拿到几笔赔偿 ,知道了吗?
- 02-18 [驾车常识] 两车同时并线,发生事故到底谁负责?看完就懂了
- 12-14 [涨姿势] 古埃及神庙发现的可能是克利奥帕特拉七世的半身像
- 12-14 [涨姿势] 谷歌的新型量子芯片解决了最好的超级计算机需要宇宙年龄四万亿倍才能破解的问题
- 12-14 [涨姿势] 新研究揭示了古代“天空圆盘”是如何制造的,粉碎了它是赝品的说法
- 12-14 [涨姿势] 器官芯片显示,眼镜蛇毒液通过血管塌陷而致人死亡
- 12-14 [涨姿势] 2000年前的岩石艺术,包括近140英尺长的蛇,可能标志着哥伦比亚和委内瑞拉的古代领土
- 12-14 [涨姿势] 嵌入人类基因组中的“化石病毒”与精神疾病有关
- 12-14 [涨姿势] 美国最新一例人类 H5N1 禽流感病例是第一个引起呼吸道症状的病例
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag