Django中为DeleteView类编写的删除关联上传图片功能无法运行如何解决
功能失效原因
- 自定义删除头图的方法未被触发:Django的
DeleteView执行删除逻辑时默认调用内置的delete()方法,你定义的delete_header_image方法没有被任何逻辑调用,永远不会执行。 - 图片路径取值错误:直接将
header_image转为字符串传入os.remove,拿到的是图片的对外访问URL路径,不是服务器本地文件系统的绝对路径,操作系统无法定位到要删除的文件。 - 权限校验逻辑存在缺陷:
test_func方法没有兜底返回值,当权限校验不满足时会返回None,会触发Django的权限校验异常。 - 头图存储路径生成逻辑错误:
get_header_image_filepath函数中直接引用self.header_image拼接路径,此时字段还未完成赋值,无法拿到正确的文件名,会导致存储路径异常。
修复方案
1. 重写DeleteView的delete方法
将删除头图的逻辑放到DeleteView默认调用的delete方法中,在删除数据库记录之前先删除本地图片文件,修复后的视图代码如下:
import os from django.views.generic.edit import DeleteView from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.urls import reverse_lazy from .models import News class NewsDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView): model = News template_name = 'news/news_delete.html' success_url = reverse_lazy('news_list') def delete(self, request, *args, **kwargs): news = self.get_object() # 先判断头图是否存在 if news.header_image: # 用.path属性获取本地绝对路径,先判断文件存在再删除避免报错 if os.path.exists(news.header_image.path): os.remove(news.header_image.path) # 调用父类原生方法完成数据库记录删除 return super().delete(request, *args, **kwargs) def test_func(self): obj = self.get_object() # 直接返回布尔值,避免无返回值的问题 return self.request.user.has_perm('news.all') or self.request.user.has_perm('news.delete_news') or obj.author == self.request.user
2. 修复头图存储路径生成逻辑
修改模型中的路径生成函数,用传入的原始文件名参数拼接路径:
def get_header_image_filepath(self, filepath): # filepath为用户上传的原始文件名,拼接生成存储路径 return f'images/news/header/{self.author.id}/{filepath}' class News(models.Model): title = models.CharField(max_length=255) header_image = models.ImageField(null=True, blank=True, upload_to=get_header_image_filepath) body = RichTextUploadingField() datetime = models.DateTimeField(auto_now_add=True) author = models.ForeignKey( AUTH_USER_MODEL, on_delete=models.CASCADE, ) def __str__(self): return self.title def get_absolute_url(self): return reverse("news_detail", args=[str(self.id)])
额外注意
请确保Django配置文件中MEDIA_ROOT配置正确,ImageField的path属性会基于MEDIA_ROOT生成本地绝对路径。
内容的提问来源于stack exchange,提问作者ali ardakani
相关产品推荐
相关产品推荐

