""" 通用文件上传视图 """ from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from rest_framework.parsers import MultiPartParser, FormParser from api_v1.models import UploadedFile from api_v1.serializers import UploadedFileSerializer, FileUploadSerializer class UploadFileViewSet(viewsets.GenericViewSet, viewsets.mixins.CreateModelMixin, viewsets.mixins.RetrieveModelMixin, viewsets.mixins.DestroyModelMixin): """ 通用文件上传 ViewSet 用于上传无法归类到具体业务的文件 retrieve: 获取单个文件信息 create: 上传新文件 destroy: 软删除文件 注意:不支持列表查询和修改操作 """ queryset = UploadedFile.objects.all() serializer_class = UploadedFileSerializer permission_classes = [IsAuthenticated] parser_classes = [MultiPartParser, FormParser] def get_queryset(self): """默认不显示已删除的文件""" queryset = super().get_queryset() # 过滤掉已删除的文件 queryset = queryset.filter(is_deleted=False) return queryset def perform_create(self, serializer): """创建时自动设置 owner""" uploaded_file = self.request.FILES.get('file') # 保存文件并记录元数据 serializer.save( owner=self.request.user, original_filename=uploaded_file.name, file_size=uploaded_file.size, content_type=uploaded_file.content_type ) def create(self, request, *args, **kwargs): """ 上传文件 使用 multipart/form-data 格式上传 """ # 验证上传的文件 upload_serializer = FileUploadSerializer(data=request.data) upload_serializer.is_valid(raise_exception=True) # 创建文件记录 file_serializer = self.get_serializer(data={'path': request.FILES['file']}) file_serializer.is_valid(raise_exception=True) self.perform_create(file_serializer) headers = self.get_success_headers(file_serializer.data) return Response( file_serializer.data, status=status.HTTP_201_CREATED, headers=headers ) def destroy(self, request, *args, **kwargs): """软删除文件(标记为已删除,不实际删除)""" instance = self.get_object() instance.is_deleted = True instance.save() return Response( {'detail': '文件已标记为删除'}, status=status.HTTP_200_OK ) @action(detail=True, methods=['post']) def restore(self, request, pk=None): """恢复已删除的文件""" instance = self.get_object() if not instance.is_deleted: return Response( {'detail': '文件未被删除,无需恢复'}, status=status.HTTP_400_BAD_REQUEST ) instance.is_deleted = False instance.save() serializer = self.get_serializer(instance) return Response({ 'detail': '文件已恢复', 'data': serializer.data }) @action(detail=True, methods=['delete']) def permanent_delete(self, request, pk=None): """永久删除文件(物理删除)""" instance = self.get_object() # 删除物理文件 if instance.path: instance.path.delete(save=False) # 删除数据库记录 instance.delete() return Response( {'detail': '文件已永久删除'}, status=status.HTTP_204_NO_CONTENT )