Приемник Django не вызывается после подключения к сигналу pre_delete - PullRequest
0 голосов
/ 26 февраля 2020

Цель

Я пытаюсь реализовать систему голосования, которая отслеживает, когда пользователь голосует по указанному c объекту в базе данных. Я отслеживаю это, используя промежуточную модель UserVote с внешним ключом к объекту, который фактически содержит все голоса. Всякий раз, когда UserVote удаляется, я хочу удалить голосование по связанному объекту.

Что я пробовал

Поскольку массовое удаление не вызывает метод model.delete() , я хочу выполнить sh вышеизложенное, прослушивая сигнал 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

Проблема

Когда я вызываю delete() для экземпляра модели в views.py, функция не вызывается. Если я добавлю операторы печати в функцию получателя, как показано ниже, ни одно из операторов не будет напечатано.

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

Я прочитал Сигнальную документацию и не нашел источника проблемы. Я поместил функцию приемника в myapp.signals и myapp.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
...

1 Ответ

0 голосов
/ 26 февраля 2020

в вашем файле app.py app добавьте импорт сигналов, он должен выглядеть следующим образом

class UsersConfig(AppConfig):
    name = 'users'

    def ready(self):
        import users.signals

, а в файле settings.py вы должны добавить свое приложение следующим образом

'users.apps.UsersConfig',

это должно вызвать сигнал pre_delete,: D я провел целый день, думая, что сделал что-то не так, когда я просто забыл эти 2 lol

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...