功能变化: 导出模板优化

pull/64/head
李强 2022-06-14 22:59:23 +08:00
parent 8817edd603
commit f768cc6dea
2 changed files with 84 additions and 10 deletions

View File

@ -7,7 +7,7 @@ from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from application import dispatch from application import dispatch
from dvadmin.system.models import Users from dvadmin.system.models import Users, Role, Dept
from dvadmin.system.views.role import RoleSerializer from dvadmin.system.views.role import RoleSerializer
from dvadmin.utils.json_response import ErrorResponse, DetailResponse from dvadmin.utils.json_response import ErrorResponse, DetailResponse
from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.serializers import CustomModelSerializer
@ -239,11 +239,33 @@ class UserViewSet(CustomModelViewSet):
"name": "用户名称", "name": "用户名称",
"email": "用户邮箱", "email": "用户邮箱",
"mobile": "手机号码", "mobile": "手机号码",
"gender": "用户性别(男/女/未知)", "gender": {
"is_active": "帐号状态(启用/禁用)", "title": "用户性别",
"choices": {
"data": [{"未知": 2}, {"": 1}, {"": 0}],
}
},
"is_active": {
"title": "帐号状态",
"choices": {
"data": [{"启用": True}, {"禁用": False}],
}
},
"password": "登录密码", "password": "登录密码",
"dept": "部门ID", "dept": {
"role": "角色ID", "title": "部门",
"choices": {
"queryset": Dept.objects.filter(status=True),
"values_list": "name"
}
},
"role": {
"title": "角色",
"choices": {
"queryset": Role.objects.filter(status=True),
"values_list": "name"
}
},
} }
@action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated]) @action(methods=["GET"], detail=False, permission_classes=[IsAuthenticated])

View File

@ -4,7 +4,8 @@ from urllib.parse import quote
from django.db import transaction from django.db import transaction
from django.http import HttpResponse from django.http import HttpResponse
from openpyxl import Workbook from openpyxl import Workbook
from openpyxl.utils import get_column_letter from openpyxl.worksheet.datavalidation import DataValidation
from openpyxl.utils import get_column_letter, quote_sheetname
from openpyxl.worksheet.table import Table, TableStyleInfo from openpyxl.worksheet.table import Table, TableStyleInfo
from rest_framework.request import Request from rest_framework.request import Request
@ -15,13 +16,28 @@ from dvadmin.utils.request_util import get_verbose_name
class ImportSerializerMixin: class ImportSerializerMixin:
""" """
自定义导模板导入功能 自定义导模板导入功能
""" """
# 导入字段 # 导入字段
import_field_dict = {} import_field_dict = {}
# 导入序列化器 # 导入序列化器
import_serializer_class = None import_serializer_class = None
# 表格表头最大宽度默认50个字符
export_column_width = 50
def get_string_len(self, string):
"""
获取字符串最大长度
:param string:
:return:
"""
length = 4
if string is None:
return length
for char in string:
length += 2.1 if ord(char) > 256 else 1
return round(length, 1) if length <= self.export_column_width else self.export_column_width
@transaction.atomic # Django 事务,防止出错 @transaction.atomic # Django 事务,防止出错
def import_data(self, request: Request, *args, **kwargs): def import_data(self, request: Request, *args, **kwargs):
@ -44,10 +60,46 @@ class ImportSerializerMixin:
"Content-Disposition" "Content-Disposition"
] = f'attachment;filename={quote(str(f"导入{get_verbose_name(queryset)}模板.xlsx"))}' ] = f'attachment;filename={quote(str(f"导入{get_verbose_name(queryset)}模板.xlsx"))}'
wb = Workbook() wb = Workbook()
ws1 = wb.create_sheet("data", 1)
ws1.sheet_state = 'hidden'
ws = wb.active ws = wb.active
row = get_column_letter(len(self.import_field_dict) + 1) row = get_column_letter(len(self.import_field_dict) + 1)
column = 10 column = 10
ws.append(["序号", *self.import_field_dict.values()]) header_data = ["序号", ]
validation_data_dict = {}
for index, ele in enumerate(self.import_field_dict.values()):
if isinstance(ele, dict):
header_data.append(ele.get('title'))
choices = ele.get('choices', {})
if choices.get('data'):
data_list = []
for data in choices.get('data'):
data_list.extend(data.keys())
validation_data_dict[ele.get('title')] = data_list
elif choices.get('queryset') and choices.get('values_list'):
data_list = choices.get('queryset').values_list(choices.get('values_list'), flat=True)
validation_data_dict[ele.get('title')] = list(data_list)
else:
continue
column_letter = get_column_letter(len(validation_data_dict))
dv = DataValidation(type="list",
formula1=f"{quote_sheetname('data')}!${column_letter}$2:${column_letter}${len(validation_data_dict[ele.get('title')]) + 1}",
allow_blank=True)
ws.add_data_validation(dv)
dv.add(f"{get_column_letter(index + 2)}2:{get_column_letter(index + 2)}1048576")
else:
header_data.append(ele)
# 添加数据列
ws1.append(list(validation_data_dict.keys()))
for index, validation_data in enumerate(validation_data_dict.values()):
for inx, ele in enumerate(validation_data):
ws1[f"{get_column_letter(index + 1)}{inx + 2}"] = ele
# 插入导出模板正式数据
df_len_max = [self.get_string_len(ele) for ele in header_data]
ws.append(header_data)
#  更新列宽
for index, width in enumerate(df_len_max):
ws.column_dimensions[get_column_letter(index + 1)].width = width
tab = Table(displayName="Table1", ref=f"A1:{row}{column}") # 名称管理器 tab = Table(displayName="Table1", ref=f"A1:{row}{column}") # 名称管理器
style = TableStyleInfo( style = TableStyleInfo(
name="TableStyleLight11", name="TableStyleLight11",