首页 > 解决方案 > 删除和恢复文件和级联文件夹 Django

问题描述

我是 django 的新手,我正在做一个类似于 google Drive 的项目。

  1. 我希望当我软删除文件夹或文件时,它应该出现在垃圾箱中(只有父文件夹,以防它有子文件夹),但不应该在媒体根文件夹中删除
  2. 我希望能够恢复文件夹(及其子文件夹,如果有的话)或文件
  3. 我还希望能够永久删除垃圾箱中的文件或文件夹

这是我写的代码

import os
import safedelete
from django.db import models
from safedelete.models import SafeDeleteModel
from safedelete.models import SOFT_DELETE_CASCADE
from safedelete.models import HARD_DELETE
from documentation.manager import *
from datetime import datetime
from django.urls import reverse
from django.utils.text import slugify
from django.db.models.signals import post_delete, pre_save
from django.dispatch import receiver
from account.models import CustomUser
from program.models import Activity

#a model to create the folder
class Folder(SafeDeleteModel):
    _safedelete_policy = SOFT_DELETE_CASCADE
    objects = MyModelManager()

    creator = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null = True)
    activity_name = models.ForeignKey(Activity, on_delete=models.CASCADE, blank = True, null=True)
    name = models.CharField(max_length=64)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    path = models.CharField(max_length=2048, blank=True)
    slug = models.SlugField(blank=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        kwargs = {'slug' : self.slug}
        return reverse('', kwargs=kwargs)

    def get_path(self):
        if self.parent: 
            yield from self.parent.get_path()
        yield self.name

        
    def complete_get_path(self):
        return "/".join(self.get_path())

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        self.path = self.complete_get_path()
        return super().save(*args, **kwargs)
    class Meta:
        unique_together = [['parent', 'name']]
        ordering = ('name',)
       
class Uploads(SafeDeleteModel):
    _safedelete_policy = SOFT_DELETE_CASCADE
    objects = MyModelManager()

    Images = 3
    Video = 2
    Documents = 1
    CHOICES = (
        (Images, 'Images'),
        (Video, 'Video'),
        (Documents, 'Documents')
        
    )
    activity_name = models.ForeignKey(Activity, on_delete=models.CASCADE, blank = True, null=True)
    doc_type = models.PositiveSmallIntegerField(choices=CHOICES, blank=True, null=False)
    doc_name = models.CharField(max_length=50)
    uploader_name = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    folder = models.ForeignKey(Folder, on_delete=models.CASCADE, blank = True, null=True)
    dete_uploaded = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)
    
    
    upload_path = models.FileField(upload_to='%Y/%m/%d', default = "files/", verbose_name = "Choose File", blank = False)


    def __str__(self):
        return self.doc_name

    class Meta:
        verbose_name_plural = "Files"


# These two auto-delete files from filesystem when they are unneeded:

@receiver(models.signals.post_delete, sender=Uploads)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """
    Deletes file from filesystem
    when corresponding `Uploads` object is deleted.
    """
    if instance.upload_path:
        if os.path.isfile(instance.upload_path.path):
            os.remove(instance.upload_path.path)

@receiver(models.signals.pre_save, sender=Uploads)
def auto_delete_file_on_change(sender, instance, **kwargs):
    """
    Deletes old file from filesystem
    when corresponding `Uploads` object is updated
    with new file.
    """
    if not instance.pk:
        return False

    try:
        old_file = Uploads.objects.get(pk=instance.pk).upload_path
    except Uploads.DoesNotExist:
        return False

    new_file = instance.upload_path
    if not old_file == new_file:
        if os.path.isfile(old_file.path):
            os.remove(old_file.path)

目前发生的事情是

  1. 当我软删除文件时,它出现在垃圾箱中,但它也被永久删除在媒体根文件夹中

  2. 当我软删除有子文件夹时,它们会单独显示在垃圾箱中

这是垃圾箱视图的代码

from rest_framework.views import APIView
from rest_framework.parsers import FileUploadParser
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from safedelete.models import HARD_DELETE
from django.http import Http404
from users.serializer import UserSerializer
from account.models import CustomUser
from documentation.models import *
from documentation.serializers import *
from rest_framework.response import Response

# Create your views here.

'''                Trash Zone                  '''
class UserFolderFileTrashView(APIView):
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]

    def get_object(self, pk):    #get deleted folder
        try:
            return Folder.objects.deleted_only().filter( creator_id = pk)
        except Folder.DoesNotExist:
            raise Http404
    def get_objects(self, pk):   #get deleted files belonging to a folder
        try:
            return Uploads.objects.deleted_only().filter( folder__id__isnull = False , uploader_name_id = pk)
        except Uploads.DoesNotExist:
            raise Http404
    def get_objectss(self, pk):  # get deleted files in the base activity
        try:
            return Uploads.objects.deleted_only().filter( activity_name__id__isnull = False , uploader_name_id = pk)
        except Uploads.DoesNotExist:
            raise Http404

   
    def get(self, request,*args, **kwargs):
        serializer = {}
        folder = self.get_object(self.kwargs.get('pk', ''))
        filee = self.get_objects(self.kwargs.get('pk', ''))
        filee2 = self.get_objectss(self.kwargs.get('pk', ''))
        serializer['folders'] = FolderSerializer(folder, many=True).data
        serializer['files_level1'] = FileSerializer(filee2, many=True).data
        serializer['files_level2'] = FileSerializer(filee, many=True).data
        return Response(serializer)

'''              Undelete / Delete File and folders from Trash        '''

#Trash Files update view
class TrashFilesUpdateView(APIView):
    parser_class = (FileUploadParser,)
    serializer_class = FileSerializer
    permission_classes = [IsAuthenticated]
    def get_object(self, pk):
        try:
            return Uploads.objects.get(pk=pk)
        except Uploads.DoesNotExist:
            raise Http404
    
    def get(self, request, *args, **kwargs):
        filee = self.get_object(self.kwargs.get('file_id', ''))
        serializer = FileSerializer(filee)
        return Response(serializer.data)
    
    def put(self, request, *args, **kwargs):
        filee = self.get_object(self.kwargs.get('file_id', ''))
        filee.undelete()
        serializer = self.serializer_class(filee, data=request.data)
        valid = serializer.is_valid(raise_exception=True)

        if valid:
            status_code = status.HTTP_201_CREATED
            serializer.save()
            return Response(serializer.data, status=status_code)

    def delete(self, request, *args, **kwargs):
        filee = self.get_object(self.kwargs.get('file_id', ''))
        filee.delete(force_policy= HARD_DELETE, **kwargs)
        return Response(status=status.HTTP_204_NO_CONTENT)

#Trash Folders update view
class TrashFoldersUpdateView(APIView):
    serializer_class = FolderSerializer
    permission_classes = [IsAuthenticated]
    def get_object(self, pk):
        try:
            return Folder.objects.get(pk=pk)
        except Folder.DoesNotExist:
            raise Http404
    def get(self, request, *args, **kwargs):
        folder = self.get_object(self.kwargs.get('folder_id', ''))
        serializer = FolderSerializer(folder)
        return Response(serializer.data)

    def put(self, request, *args, **kwargs):
        folder = self.get_object(self.kwargs.get('folder_id', ''))
        folder.undelete()
        serializer = self.serializer_class(folder, data=request.data)
        valid = serializer.is_valid(raise_exception=True)
        if valid:
            status_code = status.HTTP_201_CREATED
            serializer.save()
            return Response(serializer.data, status=status_code)
        

    def delete(self, request, *args, **kwargs):
        folder = self.get_object(self.kwargs.get('folder_id', ''))
        folder.delete(force_policy= HARD_DELETE, **kwargs)
        return Response(status=status.HTTP_204_NO_CONTENT)
    

标签: djangopyhook

解决方案


推荐阅读