删除前编辑记录。Django 删除视图

mas*_*ing 5 python django django-models django-forms django-views

我有以下型号:

class Category(models.Model):
    ....
    posts = models.PositiveIntegerField(_('numero post'), default=0)
    ....

class Post(models.Model):
    ....
    categories = models.ManyToManyField(Category, blank=True, verbose_name=_('categorie'))
    ....
Run Code Online (Sandbox Code Playgroud)

Category.posts字段计算与其所属类别相关的帖子数量。CreateView我通过以下方式将计数器增加到:

class CreatePostView(LoginRequiredMixin, CreateView):
    model = Post
    ...

    def form_valid(self, form, **kwargs):
        ...
        categories = self.object.categories.all()
        for category in categories:
            category.posts = category.posts + 1
            category.save()

        self.object.save()
        return super(CreatePostView, self).form_valid(form)
Run Code Online (Sandbox Code Playgroud)

当我删除博客文章时,我需要在删除博客文章时减少计数器Post。我尝试这样做:

class DeletePostView(LoginRequiredMixin, DeleteView):
    model = Post
    ...

    def form_valid(self, form, **kwargs):
        ...
        categories = post.categories.all()
        for category in categories:
            if (category.posts - 1) > 0:
                category.posts = category.posts - 1
                category.save()
        return post
Run Code Online (Sandbox Code Playgroud)

但它不起作用,因为在调用此方法之前记录已被删除。

在删除记录之前如何进行此操作?或者有一种内置的方法可以从中获取相关记录的数量Category

Wil*_*sem 5

form_valid由于a没有形式DeleteView,因此 a不存在DeleteView

我们能做的就是在.delete(..)函数中添加一些逻辑,也就是删除对象的函数。将其DeleteView实现为:

def delete(self, request, *args, **kwargs):
    """
    Call the delete() method on the fetched object and then redirect to the
    success URL.
    """
    self.object = self.get_object()
    success_url = self.get_success_url()
    self.object.delete()
    return HttpResponseRedirect(success_url)
Run Code Online (Sandbox Code Playgroud)

所以我们可以将其实现为:

from django.db.models import F

class DeletePostView(LoginRequiredMixin, DeleteView):

    model = Post
    # ...

    def delete(self, *args, **kwargs):
        self.object = self.get_object()
        self.object.post.categories.all().update(posts=F('posts')-1)
        return super(DeletePostView, self).delete(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

上面的代码将通过减少字段来“批量”更新类别posts。然而,在这里,它可以达到零(这在您给定的代码中是不可能的)。

如果你想防止这种情况发生,我们可以使用Greatest[Django-doc]来避免这种情况:

from django.db.models import F, Value
from django.db.models.functions import Greatest

class DeletePostView(LoginRequiredMixin, DeleteView):

    model = Post
    # ...

    def delete(self, *args, **kwargs):
        self.object.post.categories.all().update(posts=Greatest(F('posts')-1, Value(1)))
        return super(DeletePostView, self).delete(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)


小智 5

在 4.0 版本中,您将收到警告DeleteViewCustomDeleteWarning:DeleteView 使用 FormMixin 处理 POST 请求。因此,YourDeleteView.delete() 处理程序中的任何自定义删除逻辑都应移至 form_valid()。所以,继续在 form_valid 中实现你的逻辑