前言
在 DRF 中,生成 excel 表格最不便的是借助第三方插件 drf-renderer-xlsx, 使得“导出”性能变得和写一般视图一样简略、不便、快捷。其思维是基于列表,毕竟 list 办法生成的 queryset 曾经和所须要的表格构造相似了,只是须要放在表格文件中。
版本
drf-renderer-xlsx==0.4.3
Django==3.1.4
djangorestframework==3.12.4
配置
将以下配置写入 REST_FRAMEWORK
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES": [
"rest_framework.renderers.JSONRenderer",
"rest_framework.renderers.BrowsableAPIRenderer",
"drf_renderer_xlsx.renderers.XLSXRenderer",
],
}
视图
首先看一个简略的导出视图实现
from drf-renderer-xlsx import XLSXFileMixin
from drf-renderer-xlsx import XLSXRenderer
from rest_framework import viewsets, filters, mixins
class ExportViewSet(mixins.ListModelMixin, GenericViewSet, XLSXFileMixin):
renderer_classes = (XLSXRenderer,)
queryset = Model.objects.all()
serializer_class = ExportSerializer
xlsx_use_labels = True
- 导出视图就和一般的 list 视图相似,同时继承 ListModelMixin,GenericViewSet,以及咱们的配角 XLSXFileMixin
- renderer_classes 指定渲染器,必须要
- queryset 汇合
- serializer_class 序列化器
- xlsx_use_labels 默认为 False, 可要可不要,此属性的作用是设置表头的名称。默认是字段名,为 True 时,在 serializer 中 联合属性 label能够 指定表头名称为 label 值,例如
class ExportSerializer(serializers.Serializer):
name = serializers.SerializerMethodField(label="姓名")
默认表头名称为“name”,为 True 时,名称为 ” 姓名 ”
再配置 url, 向 url 申请就能够取得一个 excel 表格。简略的配置就到这里。
小结
要实现导出表格性能,须要:
- 写入配置项
- 在 list 视图的根底上,继承 XLSXFileMixin,设置渲染器 renderer、汇合 queryset、序列化器
- 要想指定表头的名称,增加 xlsx_use_labels=True,同时在序列化器中申明字段的 label 值。默认为模型的字段名。
一些其余属性及性能
在开发导出性能的时候,咱们常常会遇到一些其余的性能需要,以下都是在 视图类中的设置。
-
设置导出的文件名称
filename = "my_export.xlsx" # 设置属性 filename
默认为 export.xlsx
还能够通过编写办法去笼罩来设置文件名,办法名:get_filename() -
疏忽字段
xlsx_ignore_headers = [<fieldname>] # 疏忽的字段
此属性是设置在视图类下的,疏忽字段也能够在序列化器中实现。(序列化器如果继承的是 Serializer 不申明就能够,如果是 ModelSerializer 能够应用,也能够通过重写序列化器中的 to_representation()办法。)
-
命名布尔值
xlsx_boolean_labels = {True: _('Yes'), False: _('No')}
将布尔值中的 True 替换为 Yes,False 替换为 No,也可在 serilaizer 中解决。
- 自定义映射——xlsx_custom_cols
应用场景:就我集体来说目前遇到的应用场景是,数据库中的这个字段存储的时候就是以映射存储的,比方问卷调查的后果,每个用户的每道题答案是依据映射存储的,(比方 1,2,3)这样,导出的时候须要还原成选项文字。
def list(self, request, *args, **kwargs):
.......
for i in results:
for k,v in i.items():
self.xlsx_custom_cols.update({k: {"label": k, "formatter": v}})
return Response(results)
results 就是表格对象。遍历,映射,更新字段值
- 与 DRF 的联合:筛选、权限、排序
class ExportViewSet(viewsets.ReadOnlyModelViewSet, XLSXFileMixin):
authentication_classes = (JWTAuthentication,) # 认证
filter_backends = (BaseFilterBackend, filters.OrderingFilter) # 筛选
filter_class = ExportFilter # 筛选字段
renderer_classes = (XLSXRenderer) # 渲染器
permission_classes = (IsAuthenticated,) # 权限
queryset = Model.objects.all() # 汇合
serializer_class = ExportSerializer #序列化器
xlsx_use_labels = True # 表头名称替换
另外:
因为我的 Model 有很多状态字段须要保护,这些字段都是用带映射的 SmallIntegerField 字段做的,
在导出的时候,也须要输入映射值
例如:
model:
from django.utils.translation import gettext_lazy as _T
class Model(models.Model):
class StatusChoices(models.IntegerChoices):
PAID = 1, _T("已领取")
REFUND = 2, _T("退款")
REFUNDING = 3, _T("退款中")
UNREFUND = 4, _T("未退款")
status = models.SmallIntegerField(
default=StatusChoices.PAID,
help_text="订单状态",
choices=StatusChoices.choices,
)
serializer:
class ExportSerilaizer(serializers.Serializer):
status = serializers.SerializerMethodField(label="订单状态")
def get_status(self, instance):
return instance.get_status_display()
在序列化器中重写办法,前面跟_display(), 就能够使得字段输入为映射的中文值 > “ 已领取 ”\” 退款 ”
大部分对于字段值的更改,都能够在 serializer 中实现。
总结
第三方插件的应用,与 DRF、Django 的纯熟联合,能够使得需要实现变得多计划、更简便。开发学习中,理解源码还是比拟重要的。
参考
drf-renderer-xlsx 文档