功能变化: 导出模板优化
parent
8817edd603
commit
f768cc6dea
|
@ -7,7 +7,7 @@ from rest_framework.decorators import action
|
|||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
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.utils.json_response import ErrorResponse, DetailResponse
|
||||
from dvadmin.utils.serializers import CustomModelSerializer
|
||||
|
@ -19,7 +19,7 @@ class UserSerializer(CustomModelSerializer):
|
|||
"""
|
||||
用户管理-序列化器
|
||||
"""
|
||||
dept_name = serializers.CharField(source='dept.name',read_only=True)
|
||||
dept_name = serializers.CharField(source='dept.name', read_only=True)
|
||||
role_info = DynamicSerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
|
@ -30,7 +30,7 @@ class UserSerializer(CustomModelSerializer):
|
|||
"post": {"required": False},
|
||||
}
|
||||
|
||||
def get_role_info(self, instance,parsed_query):
|
||||
def get_role_info(self, instance, parsed_query):
|
||||
roles = instance.role.all()
|
||||
|
||||
# You can do what ever you want in here
|
||||
|
@ -239,11 +239,33 @@ class UserViewSet(CustomModelViewSet):
|
|||
"name": "用户名称",
|
||||
"email": "用户邮箱",
|
||||
"mobile": "手机号码",
|
||||
"gender": "用户性别(男/女/未知)",
|
||||
"is_active": "帐号状态(启用/禁用)",
|
||||
"gender": {
|
||||
"title": "用户性别",
|
||||
"choices": {
|
||||
"data": [{"未知": 2}, {"男": 1}, {"女": 0}],
|
||||
}
|
||||
},
|
||||
"is_active": {
|
||||
"title": "帐号状态",
|
||||
"choices": {
|
||||
"data": [{"启用": True}, {"禁用": False}],
|
||||
}
|
||||
},
|
||||
"password": "登录密码",
|
||||
"dept": "部门ID",
|
||||
"role": "角色ID",
|
||||
"dept": {
|
||||
"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])
|
||||
|
|
|
@ -4,7 +4,8 @@ from urllib.parse import quote
|
|||
from django.db import transaction
|
||||
from django.http import HttpResponse
|
||||
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 rest_framework.request import Request
|
||||
|
||||
|
@ -15,13 +16,28 @@ from dvadmin.utils.request_util import get_verbose_name
|
|||
|
||||
class ImportSerializerMixin:
|
||||
"""
|
||||
自定义导出模板、导入功能
|
||||
自定义导入模板、导入功能
|
||||
"""
|
||||
|
||||
# 导入字段
|
||||
import_field_dict = {}
|
||||
# 导入序列化器
|
||||
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 事务,防止出错
|
||||
def import_data(self, request: Request, *args, **kwargs):
|
||||
|
@ -44,10 +60,46 @@ class ImportSerializerMixin:
|
|||
"Content-Disposition"
|
||||
] = f'attachment;filename={quote(str(f"导入{get_verbose_name(queryset)}模板.xlsx"))}'
|
||||
wb = Workbook()
|
||||
ws1 = wb.create_sheet("data", 1)
|
||||
ws1.sheet_state = 'hidden'
|
||||
ws = wb.active
|
||||
row = get_column_letter(len(self.import_field_dict) + 1)
|
||||
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}") # 名称管理器
|
||||
style = TableStyleInfo(
|
||||
name="TableStyleLight11",
|
||||
|
|
Loading…
Reference in New Issue