连接到 pre_delete 信号后未调用 Django 信号接收器

Django signal reciever not called after connecting to pre_delete signal

目标

我正在尝试实现一个投票系统来跟踪用户何时对数据库中的特定对象进行投票。我正在使用一个中间 UserVote 模型跟踪它,该模型具有指向实际包含所有选票的对象的外键。每当 UserVote 被删除时,我想删除对相关对象的投票。

我试过的

Since bulk deletes do not call the model.delete() method,我想通过监听pre_delete信号来完成上面的事情。

当我使用 Django 测试运行程序测试以下接收器函数时,一切都按预期运行

from myapp.models.users import UserVote
from django.db.models.signals import pre_delete
from django.dispatch import receiver


@receiver(pre_delete)
def user_vote_handler(sender, instance, **kwargs):
    if sender in UserVote.__subclasses__():
        # remove the vote from the related model

问题

当我在 views.py 中的模型实例上调用 delete() 时,该函数未被调用。如果我如下所示将打印语句添加到接收函数,则会打印 none 个语句。

from myapp.models.users import UserVote
from django.db.models.signals import pre_delete
from django.dispatch import receiver


@receiver(pre_delete)
def user_vote_handler(sender, instance, **kwargs):
    print('function called')
    if sender in UserVote.__subclasses__():
        print('condition met')
        # remove the vote from the related model

我已经通读了Signal Documention,但我还没有找到问题的根源。我将接收函数放在 myapp.signalsmyapp.models.users 中,行为是相同的。我有一种感觉,我做了一些愚蠢的事情,但还没有意识到。任何人都可以阐明可能出了什么问题吗?我正在使用 Django 2.2。

代码

# models.records.py
...


class Record(models.Model):
    ...
    # some functions for all Record subclasses
    ....


class Author(Record):
    name = models.CharField(max_length=255)
    comments = models.ManyToManyField(
        Comment,
        through='ForumComment',
        through_fields=('author', 'comment'),
    )
    ...
    # some functions specific to this
    ....

...
# more records
...
# models.comments.py
...


class RecordComment(models.Mode):
    text = label = models.CharField(max_length=255)
    ...
    # some methods
    ...


class AuthorComment(RecordComment):
    ...
    # methods specific to AuthorComment
    ...

...
# more RecordComment subclass
...


class Comment(models.Model):
    class Meta:
        abstract = True

    up_votes = models.PositiveIntegerField(blank=True, default=0)
    down_votes = models.PositiveIntegerField(blank=True, default=0)


class ForumComment(Comment):
    author = models.ForeignKey('myapp.Author', on_delete=models.CASCADE, verbose_name='related record')
    comment = models.ForeignKey(AuthorComment, on_delete=models.CASCADE)
...
# more types of comments
...
# models.users.py
...


class User(AbstractUser):
    pass


class UserVote(models.Model):
    """shared fields and functions for UserVote models"""
    class Meta:
        abstract = True

    DOWN_VOTE = 'DOWN'
    UP_VOTE = 'UP'
    VOTE_CHOICES = [
        (DOWN_VOTE, 'Down vote'),
        (UP_VOTE, 'Up vote'),
    ]
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    vote = models.CharField(choices=VOTE_CHOICES, default=UP_VOTE, max_length=255)
    ...
    # methods to handle voting
    ...


class ForumCommentUserVote(UserVote):
    forum_comment = models.ForeignKey('myapp.ForumComment', on_delete=models.CASCADE)

        class Meta:
        constraints = [
            models.UniqueConstraint(fields=['forum_comment', 'user'], name='unique_author_tag_assignment_user_vote')
        ]
    ...
    # some more methods
    ...
...
# more UserVote subclasses
...

在您的应用程序 app.py 文件中添加信号导入,它应该如下所示

class UsersConfig(AppConfig):
    name = 'users'

    def ready(self):
        import users.signals

并且在 settings.py 中你应该像这样添加你的应用程序

'users.apps.UsersConfig',

这应该会触发 pre_delete 信号,:D 我花了一整天的时间以为我做错了什么,但实际上我只是忘记了这两个 lol