Цель
Я пытаюсь реализовать систему голосования, которая отслеживает, когда пользователь голосует по указанному 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
...