ali ardakani
ali ardakani

Reputation: 82

The extra function written for the DeleteView class does not work

I have added a function that if the post is deleted by the user, it will be deleted if there is an uploaded photo, but the function does not work.

my view:

class NewsDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = News
    template_name = 'news/news_delete.html'
    success_url = reverse_lazy('news_list')

    def delete_header_image(self, pk):
        news = get_object_or_404(News, id = pk)
        header_image = news.header_image
        if header_image is not None:
            os.remove(str(header_image))
            return HttpResponseRedirect(reverse('news_list'))
        else:
            return HttpResponseRedirect(reverse('news_list'))

    def test_func(self):
        obj = self.get_object()
        if self.request.user.has_perm('news.all') or self.request.user.has_perm('news.delete_news') or obj.author == self.request.user:
            return True 

urls:

urlpatterns = [
    path('<int:pk>/delete', NewsDeleteView.as_view(), name='news_delete'),
] 

models:

def get_header_image_filepath(self, filepath):
    return f'images/news/header/{self.author.id}/{self.header_image}'


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)])

Upvotes: 1

Views: 251

Answers (1)

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21822

Class based views do not work magically. They have some methods already written which are called to perform actions. Hence you writing a method delete_header_image does not mean it will be called automatically. Instead you should override some suitable method of the class which will be called internally. For DeleteView the method that performs the deletion is delete and hence you should override that. Also the condition if header_image is not None will not work since even if there is no file it will not be represented by None instead you should simply write if header_image for checking. Furthermore instead of deleting manually simply call ieldFile.delete [Django Docs]:

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):
        object = self.get_object()
        if object.header_image:
            object.header_image.delete(save=False)
        return super().delete(request, *args, **kwargs)

    def test_func(self):
        obj = self.get_object()
        if self.request.user.has_perm('news.all') or self.request.user.has_perm('news.delete_news') or obj.author == self.request.user:
            return True

Upvotes: 1

Related Questions