[每日一学] django ImportExportModelAdmin自定义导出数据
作者:CC下载站 日期:2020-09-23 00:00:00 浏览:69 分类:涨姿势
官方文档: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)
效果如图:
猜你还喜欢
- 06-29 [涨姿势] 鱼丸批量化生产流程,什么是鱼丸加工流水线?都有哪些设备组成?
- 06-29 [涨姿势] 食为先培训的陷阱和套路?凉菜不是你想卖就能卖?
- 06-29 [涨姿势] 开面馆不是梦,但也不是人人都能驾驭
- 05-13 [摄影] 让手机秒变单反的手机拍摄好物
- 05-11 [摄影] 想挣钱的摄影师建议收藏!
- 05-11 [美食] 选址秘籍:从摆摊到开小店,大数据地图助你找到理想店铺位置
- 05-04 [知识分享] 「科普」不知道电影资源那么长一大串名字是什么意思?看完这个你就明白了!
- 04-30 [摄影] 玩转手机摄影 | 滤镜手机支架
- 04-30 [经验] 摆地摊的八大禁忌
- 04-27 [绘画] 油画棒原创作品【绽放】图文教程来咯~
- 04-17 [涨姿势] 餐饮管理故事:对不起,我订错了雅间,怎么办?(附解决方案)
- 03-29 [摄影课堂] 电光火石间的决定
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[美剧] 史密斯夫妇.2024.8集全.4K.附影版
[电影] 最佳拍档5:兵马俑风云(含前4部全合集)[喜剧/动作/犯罪]
[有声小说] 《都市风水师》 作者:听叶 主播:原野 434集完【MP3】
[电影] 重启2000之传奇人生(84集)
[有声小说] 《百炼成神》 主播:令狐笑笑生&浥轻尘 3913集完【MP3】 [40.3G]
[有声小说] 《傲世九重天》 作者:风凌天下 主播:我影随风 2323集完结【MP3】
[美剧] 《女巫阿加莎》2024 [1080P BD][英语 中英双语字幕][1-9集全]
[美剧] 企鹅人 The Penguin (2024) 1080P 全8集完结
[电视剧] 我们在黑夜中相拥 (2024) 1080 横屏短剧 更24完结
[书籍] 经典科普书籍合集30套近300部·完美精校全插图收藏版
[书籍] 彭子益医书合集 [PDF/DOC]
[游戏] 《黑神话悟空》免安装学习版【全dlc整合完整版】+Steam游戏解锁+游戏修改工具!
[动画] 《名侦探柯南》名侦探柯南百万美元的五菱星 [TC] [MP4]
[动画] 2002《火影忍者》720集全【4K典藏版】+11部剧场版+OVA+漫画 内嵌简日字幕
[剧集] 《斯巴达克斯》1-4季合集 无删减版 1080P 内嵌简英特效字幕
[CG剧情] 《黑神话:悟空》158分钟CG完整剧情合集 4K120帧最高画质
[电影] 《变形金刚系列》七部合集 [4K HDR 蓝光] 国英双语音轨 [内封精品特效字幕]【典藏版】235G
[游戏] 黑神话悟空离线完整版+修改器
[动画] 收藏版:1996-2024年名侦探柯南全系列1080P,含国配、日配双语版+26部剧场作品
[动画] 西游记 (1999) 动画版 4K 全52集 高清修复版 童年回忆
[电影] 《黄飞鸿》全系列合集
[Android] 开罗游戏 ▎像素风格的模拟经营的游戏厂商安卓游戏大合集
[游戏合集] 要战便战 v0.9.107 免安装绿色中文版
[电影] 【珍藏版】20世纪电影合集从1922年到1990年代,看看爷爷辈的电影是什么样合集约212G
[书籍] 彭子益医书合集 [PDF/DOC]
[系统]【黑果小兵】macOS Big Sur 11.0.1 20B50 正式版 with Clover 5126 黑苹果系统镜像下载
[美图] 【经典收藏美图集合】1500多张韩国美女高清图片让你的收藏夹更加丰富多彩
[写真] 宫本桜 碧蓝航线 能代本典藏版-全套福利付费写真
[瓜] 青岛【路虎女】插队、逆行、追尾、打人未删减【完整版视频】
[电视剧] 灵魂摆渡(1-3季合集)【未删减】【4K.无水印】【剧情/恐怖/惊悚】【豆瓣8.7】
- 最新评论
-
一部不错的经典科幻kelvin 评论于:11-13 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢285552528 评论于:11-09 找了好久的资源bjzchzch12 评论于:11-07 谢谢分享感谢ppy2016 评论于:11-05 谢谢分享感谢ppy2016 评论于:11-05 有靳东!嘻嘻奥古斯都.凯撒 评论于:10-28 流星花园是F4处女作也是4人集体搭配的唯一一部!奥古斯都.凯撒 评论于:10-28 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢AAAAA 评论于:10-26 找了好久的资源,终于在这里找到了。感谢本站的资源和分享。谢谢password63 评论于:10-26 找了好久的资源,终于在这里找齐了!!!!blog001 评论于:10-21
- 热门tag