diff --git a/apps/ecm/views.py b/apps/ecm/views.py index 88526987..82b4331e 100644 --- a/apps/ecm/views.py +++ b/apps/ecm/views.py @@ -4,13 +4,14 @@ from threading import Thread from django.db import transaction from django.db.models import Count, F from django.utils import timezone +from rest_framework import serializers from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin) from rest_framework.response import Response - +from rest_framework.exceptions import ParseError from apps.ecm.filters import EventFilterSet from apps.ecm.models import (AlgoChannel, Event, EventCate, Eventdo, NotifySetting, Remind) @@ -23,7 +24,10 @@ from apps.ecm.serializers import (AlgoChannelCreateSerializer, NotifySettingsSerializer, RemindSerializer) from apps.ecm.service import update_remind_read from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet +from apps.utils.export import export_excel_img +obj_cate_dict = {'people': '人员', 'operation': '作业', 'other': '其他'} +mark_dict = {10: '正常', 20: '误报'} # Create your views here. class EventCateViewSet(CreateModelMixin, UpdateModelMixin, ListModelMixin, CustomGenericViewSet): @@ -138,6 +142,49 @@ class EventViewSet(ListModelMixin, RetrieveModelMixin, DestroyModelMixin, Custom 'cate', 'cate__name', 'cate__trigger').annotate(count=Count('cate'))) return Response(ret) + @action(methods=['get'], detail=False, perms_map={'get': '*'}, + serializer_class=serializers.Serializer) + def export_excel(self, request, pk=None): + """导出excel + 导出excel + """ + field_data = [ + {"name": "事件种类", "type": "str"}, + {"name": "发生区域", "type": "str"}, + {"name": "事件类型", "type": "str"}, + {"name": "事件对象", "type": "str"}, + {"name": "发生时间", "type": "str"}, + {"name": "处理人", "type": "str"}, + {"name": "事件标记", "type": "str"}, + {"name": "抓拍图", "type": "img"}, + {"name": "人脸图", "type": "img"}, + ] + queryset = self.filter_queryset(self.get_queryset()) + if queryset.count() > 200: + raise ParseError('数量超过200,请筛选后导出') + odata = EventSerializer(queryset, many=True).data + # 处理数据 + data = [] + + for i in odata: + cates_str = '' + for m in i['cates_']: + cates_str = cates_str + '/' + m['name'] + data.append( + [ + cates_str, + i['area_'].get('name', ''), + obj_cate_dict[i['obj_cate']], + 'test', + i['create_time'], + i['handle_user_name'], + mark_dict[i['mark']], + i['global_img'], + i['face_img'] + ] + ) + return Response({'path': export_excel_img(field_data, data, '事件记录')}) + class RemindViewSet(ListModelMixin, CustomGenericViewSet): perms_map = {'get': '*'} diff --git a/apps/utils/export.py b/apps/utils/export.py index 5a1b61b5..26c5e3b8 100644 --- a/apps/utils/export.py +++ b/apps/utils/export.py @@ -3,7 +3,9 @@ import time import os from django.conf import settings from datetime import datetime - +from openpyxl import Workbook, styles +from openpyxl.drawing.image import Image +from openpyxl.utils import get_column_letter, column_index_from_string def len_byte(value): # 获取字符串长度,一个中文的长度为2 @@ -16,7 +18,6 @@ def len_byte(value): def export_excel(field_data: list, data: list, FileName: str): """ Excel导出 - :param request: 请求request :param data: 数据源 :param field_data: 首行数据源(表头) :param file_path: 文件保存路径(默认保存在media路径) @@ -109,3 +110,51 @@ def export_excel(field_data: list, data: list, FileName: str): path_name = os.path.join(pathRoot, FileNameF) wbk.save(path_name) return path + FileNameF + +def export_excel_img(field_data: list, data: list, FileName: str): + """ + 带有image的Excel导出 + :param data: 数据源 + :param field_data: 首行数据源(表头){'name':'', 'type':''} + :param img_field_indexs: 图片字段名index列表 + :param file_path: 文件保存路径(默认保存在media路径) + :param FileName: 文件保存名字 + :return:返回文件的下载url完整路径 + """ + wb = Workbook() + ws = wb.active + imgs = [] + + for index, value in enumerate(field_data): + cell = ws.cell(column=index, row=0) + cell.value = value['name'] + cell.font = styles.Font(bold=True) + letter = get_column_letter(index+1) + value['letter'] = letter + ws.column_dimensions[letter].width = 10 #修改列宽 + if value['type'] == 'img': + ws.column_dimensions[letter].width = 15 #修改列宽 + + + for i1, v1 in enumerate(data): + for i2, v2 in enumerate(v1): + cell = ws.cell(column=i2, row=i1+1) + if v2 and field_data[i2]['type'] == 'img': + ws.row_dimensions[i1+1].height = 70 + img = Image(settings.BASE_DIR + v2, width=90, height=90) + imgs.append((img, field_data[i2]['letter'] +str(i1+1))) + else: + cell.value = v2 + + for i in imgs: + ws.add_image(i[0], i[1]) + + FileNameF = FileName + datetime.now().strftime('%Y%m%d%H%M%S') + '.xlsx' + path = '/media/temp/' + pathRoot = settings.BASE_DIR + path + if not os.path.exists(pathRoot): + os.makedirs(pathRoot) + + path_name = os.path.join(pathRoot, FileNameF) + wb.save(path_name) + return path + FileNameF \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2ad42d12..3c27fbe2 100755 --- a/requirements.txt +++ b/requirements.txt @@ -29,4 +29,5 @@ protobuf==3.20.1 pycryptodome==3.15.0 aliyun-python-sdk-core==2.13.36 xlwt==1.3.0 +openpyxl==3.1.0