django post_delete() 信号处理程序不起作用

Posted

技术标签:

【中文标题】django post_delete() 信号处理程序不起作用【英文标题】:django post_delete() signal handler doesn't work 【发布时间】:2018-02-04 22:06:03 【问题描述】:

我正在尝试使博客对象的“num_posts”字段在每次删除属于该博客的帖子时递减,并在每次创建帖子时递增。我能够很容易地实现重载的保存方法:

def save(self, *args, **kwargs):
    '''After saving a new post, increment the num_posts value in the
    relevant blog.'''
    super(Posts, self).save(*args, **kwargs)
    self.blog_id.num_posts += 1
    tmp = self.blog_id
    tmp.save()

但无论出于何种原因,删除 Posts 对象时的逻辑都不起作用。我通过在信号子模块的handlers.py 文件中使用信号处理程序来遵循最佳实践。然后我在apps.pyTasksConfig(Appconfig) 方法中的ready() 方法中导入子模块

我似乎没有遇到任何语法错误,或者根本没有任何错误。相关博客上的 num_posts 字段根本无法减少。以下是相关代码:

来自我的handlers.py

from django.db.models.signals import pre_delete
from django.dispatch import receiver
from webcomics.models import Pages, Posts, Blogs

@receiver(pre_delete, sender=Pages)
def handle_page_delete(sender, **kwargs):
    obj = kwargs['instance']

    if(obj != None):
        tmp1 = obj.prev_id
        tmp2 = obj.next_id

    if(tmp1 != None):
        tmp1.next_id = tmp2
        obj.prev_id = None

    if(tmp2 != None):
        tmp2.prev_id = tmp1
        obj.next_id = None


@receiver(pre_delete, sender=Posts)
def handle_bpost_delete(sender, **kwargs):
    obj = kwargs['instance']

    if(obj != None):
        tmp = Blogs.objects.get(pk = obj.blog_id)
        tmp.num_pages = tmp.num_pages - 1

来自我的apps.py

from django.apps import AppConfig

class WebcomicsConfig(AppConfig):
    name = 'webcomics'


class TasksConfig(AppConfig):
    name = 'tasks'
    verbose_name = "Tasks"

    def ready(self):
        import binshellpress.webcomics.signals.handlers

另外,这里是 models.py 中的完整 Posts 对象,以防万一你们看到我遗漏的东西:

class Posts(models.Model):
    title = models.CharField(max_length=180)
    pub_date = models.DateTimeField('date publishied', default=timezone.now)
    blog_id = models.ForeignKey('Blogs', on_delete=models.CASCADE)
    series_id = models.ForeignKey('Series', on_delete=models.SET_NULL,
                                  blank=True, null=True)

    # Note: Vanilla TinyMCE Integration seems to be working. Need to
    # modify the implementation to handle links, images, etc.
    data = htmlField()

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        '''After saving a new post, increment the num_posts value in the
        relevant blog.'''
        super(Posts, self).save(*args, **kwargs)
        self.blog_id.num_posts += 1
        tmp = self.blog_id
        tmp.save()

我怀疑这是显而易见的。我只是不知所措,因为似乎没有任何错误消息来自任何地方。

【问题讨论】:

你为什么要测试kwargs["instance"] == Nonepre_delete 信号总是会传递一个实例,或者出现严重错误。而Blogs.num_posts 可以简单地定义为返回self.pages_set.count() 的属性。这将比手动添加和减去更不容易出错。 【参考方案1】:

您忘记将更新后的Blogs 实例保存在handle_bpost_delete

def handle_bpost_delete(sender, instance, **kwargs):
    instance.blog.num_pages -= 1
    instance.blog.save()

不过,有一种更简单的方法可以获取相关对象的数量。您可以简单地让数据库在需要时进行计数。相当快,而且更不容易出错。

例子:

from django.db.models import Count

blogs = Blogs.objects.annotate(num_pages=Count('posts'))
print(blogs[0].num_pages) 

https://docs.djangoproject.com/en/1.11/topics/db/aggregation/#following-relationships-backwards

【讨论】:

以上是关于django post_delete() 信号处理程序不起作用的主要内容,如果未能解决你的问题,请参考以下文章

django 信号

django(12)信号

django内置组件

响应 Django 中的模型更改?

如何在django2.0.6中的通用删除视图中添加用户身份验证

Django如何在用户删除后删除用户的个人资料和帖子以及所有关联?