Django项目File模型软删除触发RecycleBin参数错误问题
Django软删除File模型时RecycleBin创建报错
问题描述
在Django项目中,通过重写模型delete方法、设置is_deleted=True实现软删除,回收站模型RecycleBin在其他模型中运行正常,但操作File模型删除文件时,出现错误:
RecycleBin() got unexpected keyword arguments: 'title', 'content_type', 'object_id', 'deleted_by'
相关代码
RecycleBin模型
class RecycleBin(models.Model): title = models.CharField( max_length=1000, verbose_name="Title", null=False, blank=False, ) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() deleted_object = GenericForeignKey("content_type", "object_id") deleted_by = models.ForeignKey( "Accounts.User", verbose_name="Deleted By", on_delete=models.CASCADE, blank=False, null=False, related_name="deleted_by", ) tenant = models.ForeignKey( "Tenants.Tenant", verbose_name="Tenant", max_length=1000, null=False, blank=False, on_delete=models.CASCADE, ) date_deleted = models.DateTimeField(verbose_name="Date Deleted", auto_now_add=True) due_deletion_date = models.DateTimeField(verbose_name="Due Deletion", default=None, null=True, editable=False)
File模型及管理器
class AllFilesManager(models.Manager): def get_queryset(self): return super().get_queryset() class ActiveFileModelManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(is_deleted=False) class File(models.Model): uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) name = models.CharField(max_length=1000, null=False, blank=False) folder = models.ForeignKey( "Folders.Folder", on_delete=models.CASCADE, null=False, blank=False ) file = models.FileField( upload_to='tenants', storage=storage, max_length=1000, null=False, blank=False ) is_deleted = models.BooleanField(default=False, verbose_name="Is Deleted?") created_by = models.ForeignKey( "Accounts.User", verbose_name="Created By", on_delete=models.CASCADE, blank=False, null=False, related_name="file_created_by", ) modified_by = models.ForeignKey( "Accounts.User", verbose_name="Modified By", on_delete=models.CASCADE, blank=True, null=True, related_name="file_modified_by", ) tenant = models.ForeignKey( "Tenants.Tenant", verbose_name="Tenant", max_length=1000, on_delete=models.CASCADE, null=False, blank=False, ) date_created = models.DateTimeField(verbose_name="Date Created", auto_now_add=True) date_modified = models.DateTimeField(verbose_name="Date Modified", auto_now=True) objects = ActiveFileModelManager() all_objects = AllFilesManager() def delete(self, using=None, keep_parents=False, user=None): bin = RecycleBin.objects.create( title=self.name, content_type=ContentType.objects.get_for_model(self), object_id=self.pk, deleted_by=self.modified_by, tenant=self.tenant, ) if bin: self.is_deleted = True self.modified_by = user self.save()
FileAPIView视图
class FileAPIView(APIView): def delete(self, request, pk=None): ids = request.data.get("ids", []) if len(ids) == 0: try: file = get_object_or_404(File, id=pk) file.delete() return JsonResponse( { "status": status.HTTP_204_NO_CONTENT, "message": "File moved to the Recycle Bin successfully!", } ) except Exception as e: return JsonResponse( { "status": status.HTTP_500_INTERNAL_SERVER_ERROR, "message": "An error occurred while deleting the file!", "results": {"error": str(e)}, } ) else: try: for id in ids: file = get_object_or_404(File, id=id) file.delete() return JsonResponse( { "status": status.HTTP_204_NO_CONTENT, "message": "Files moved to the Recycle Bin successfully!", } ) except Exception as e: return JsonResponse( { "status": status.HTTP_500_INTERNAL_SERVER_ERROR, "message": "An error occurred while deleting the files!", "results": {"error": str(e)}, } )
解决方法
问题核心
错误的本质是:
- API视图调用
file.delete()时未传入当前用户参数,导致File.delete()方法中user为None; File模型的modified_by字段允许为null,若某个文件从未被修改过,self.modified_by就是None,而RecycleBin的deleted_by字段不允许为null,此时Django会将无效赋值转化为关键字参数不匹配的错误提示。
修复步骤
在API视图中传递当前用户
修改FileAPIView里的file.delete()调用,传入当前请求的用户:# 单个文件删除 file.delete(user=request.user) # 批量删除循环内 file.delete(user=request.user)修正File.delete()方法的deleted_by赋值逻辑
优先使用传入的user作为删除人,避免modified_by为None的情况:def delete(self, using=None, keep_parents=False, user=None): # 确保deleted_by不为空,优先用传入的user, fallback到创建人 deleted_user = user or self.created_by bin = RecycleBin.objects.create( title=self.name, content_type=ContentType.objects.get_for_model(self), object_id=self.pk, deleted_by=deleted_user, tenant=self.tenant, ) if bin: self.is_deleted = True self.modified_by = user self.save()可选:限制modified_by字段为非空
如果业务要求文件必须有修改人,可以修改File模型的modified_by字段,移除null=True并设置默认值(可通过信号自动关联创建人):modified_by = models.ForeignKey( "Accounts.User", verbose_name="Modified By", on_delete=models.CASCADE, blank=False, null=False, related_name="file_modified_by", )
内容的提问来源于stack exchange,提问作者CoderS
相关产品推荐
相关产品推荐

