【问题标题】:Django model delete method not overridingDjango模型删除方法不覆盖
【发布时间】:2021-07-29 04:49:12
【问题描述】:

我目前正在开发一个 Django 博客应用程序,其中我有一个 Post 连接到一个 CategoryCategory 具有 nametimes_used 字段。 times_used 将在创建 Post 后增加 1,并且我已经实现了覆盖 Post 模型上的 save() 方法。我正在尝试覆盖 delete() 方法以将当前帖子的类别减 1,但它实际上并没有达到似乎覆盖的 delete() 方法,因为即使在帖子被删除后类别仍然具有增量值。请参阅下面的代码...

model.py

class Category(models.Model):
    name = models.CharField(max_length=150, unique=True)
    times_used = models.IntegerField(default=0)


class Post(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    # This increments this category by 1 then saves the post - Works well!
    def save(self, *args, **kwargs):
        self.category.times_used += 1
        self.category.save()

        super(Post, self).save(*args, **kwargs)

    # This decrements this category by 1 then deletes the post - Which is not working...
    def delete(self, *args, **kwargs):
        self.category.times_used -= 1
        self.category.save()

        super(Post, self).delete(*args, **kwargs)

有什么建议可以做到这一点吗?

【问题讨论】:

  • 你能说明你是如何删除Post的吗?
  • 我只是从管理站点中删除。然而,我读到了Django signals 并找到了一种方法来实现我想要的。不过感谢您的回复。
  • 是的,我在问这个问题,因为在覆盖 delete 时,如何删除非常重要;)
  • 根据我的理解,只要我们想使用 QuerySet 批量删除对象,覆盖方法将不起作用。

标签: python django django-models django-signals


【解决方案1】:

我刚刚阅读了有关 Django 信号的信息,并且已经完成了我想做的事情。根据 Django documentation...,当我们重写它以使用 QuerySet 批量删除对象时,不会调用 delete() 方法。所以最好使用信号来完成这些类型的工作。

在我的models.py 中,我将Post 作为参数传递给我在signals.py 中创建的函数

models.py

class Post(models.Model):
    ....

delete_post_signal(Post)

在我的signals.py 中,我有以下代码...

from django.dispatch import receiver
from django.db.models.signals import pre_delete


def delete_post_signal(Post):

    @receiver(pre_delete, sender=Post)
    def decrement_category_usage(sender, instance, **kwargs):
        instance.category.times_used -= 1
        instance.category.save()

这对我来说非常有用......

【讨论】:

    【解决方案2】:

    你可以像这样使用 pre_delete 信号来做到这一点

    @receiver(pre_delete, sender=Post)
    def my_handler(sender, instance, **kwargs):
        instance.category.times_used -= 1
        instance.category.save()
    

    【讨论】:

    • 我一开始尝试过这种方法,但出现错误...InvalidTemplateLibrary: Invalid template library specified. ImportError raised when trying to load 'blog.templatetags.custom_tags': cannot import name 'Post' fr om partially initialized module 'blog.models' 所以我不得不想出另一种方法。看我的回答。
    • 这是由于循环导入而发生的。您可以通过以这种方式from blog import models 导入模型来解决此问题,然后在代码中调用您的模型blog.models.Post 或使用get_model 函数django docs 这种方式from django.apps import apps Post = apps.get_model("blog.Post")
    • 请注意,我目前没有在我的apps.py 中使用ready() 方法。这就是我为每次调用删除帖子 delete_post_signal(Post) 所做的设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多