Django上传新文件时通过id删除用户此前已上传旧文件的实现方法
问题核心修正
你想通过id = self.id - 1获取旧文件的逻辑完全不可行:Django模型的主键ID是全局自增的,所有用户的简历共用同一条ID序列,你拿到的减1后ID大概率属于其他用户的简历,根本取不到当前用户的旧文件。
你的场景里用户和简历是一对一关联,每个用户只会有一条简历记录,直接按用户维度查询旧记录即可,以下是可直接落地的修改方案:
方案1:修改视图逻辑(最快生效)
你当前POST提交时没有绑定已有实例,每次都会尝试创建新的ResumeDocument记录,甚至会因为OneToOneField的唯一约束报错。修改pdf_resume视图的POST处理逻辑即可:
@login_required def pdf_resume(request): # 提前查询当前用户的旧简历 user_resume = ResumeDocument.objects.filter(user=request.user).first() if request.method == 'POST': # 有旧记录就绑定instance,执行更新;没有就新建 form = DocumentForm(request.POST, request.FILES, instance=user_resume) if form.is_valid(): form.instance.user = request.user # 保存前先删除旧物理文件 if user_resume and user_resume.cvfile: # 只有上传了新文件才删旧的 if form.cleaned_data.get('cvfile'): user_resume.cvfile.delete(save=False) form.save() return redirect('pdf_resume') if 'delete' in request.GET: return delete_item(ResumeDocument, request.GET['id']) else: form = DocumentForm(instance=user_resume) documents = [user_resume] if user_resume else [] context = { 'form':form, 'documents':documents, } return render(request, 'reg/pdf_resume.html', context)
方案2:重写模型方法(复用性更高)
如果不想每次在视图里写删除逻辑,可以直接在ResumeDocument模型里增加自动清理逻辑,一劳永逸:
import os from django.db import models from django.contrib.auth.models import User def validate_file_extension(value): # 你的原有验证逻辑 pass class ResumeDocument(models.Model): id = models.AutoField(primary_key=True) user = models.OneToOneField(User, on_delete=models.CASCADE) cvfile = models.FileField(upload_to="documents", null=True, validators= [validate_file_extension]) @property def filename(self): return os.path.basename(self.cvfile.name) if self.cvfile else "" def save(self, *args, **kwargs): # 更新记录时自动删除旧文件 if self.pk: old_obj = ResumeDocument.objects.get(pk=self.pk) if old_obj.cvfile and old_obj.cvfile != self.cvfile: old_obj.cvfile.delete(save=False) super().save(*args, **kwargs) def delete(self, *args, **kwargs): # 删除记录时自动删除关联文件 if self.cvfile: self.cvfile.delete(save=False) super().delete(*args, **kwargs)
用这个方案你不需要改原有视图逻辑,只要模型执行保存/删除操作就会自动清理旧文件。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

