#python #django #django-models #django-views #django-signals
#python #django #django-модели #django-просмотры #django-сигналы
Вопрос:
Я пытаюсь использовать pre_delete
сигнал для Like
модели моего приложения Django. Like
Модель имеет Book
внешний ключ. В Book
модели есть num_of_likes
поле. В конечном счете, я пытаюсь обновить это num_of_likes
поле из своего pre_delete
сигнала. Просто я не мог этого сделать.
Я думаю, что мой код сделает проблему предельно ясной (пожалуйста, обратите особое внимание на комментарии и инструкции печати):
books/models.py:
class Book(models.Model):
num_of_likes = models.IntegerField()
likes/models.py:
class Like(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey(Book)
likes/views.py:
class DeleteLikeView(APIView):
def post(self, request, book):
book = get_object_or_404(Book, id=book)
print(book.num_of_likes) # Prints, say, 10
like = Like.objects.get(user=request.user, book=book)
like.delete() # triggers signal handler below (should update `book.num_of_likes`)
print(book.num_of_likes) # Still prints 10, expected 9 <------ PROBLEM
return ...
likes/signals.py:
@receiver(pre_delete, sender=Like)
def delete_book_like(sender, instance, **kwargs):
print(instance.book.num_of_likes) # Prints 10
instance.book.num_of_likes -= 1
instance.book.save()
print(instance.book.num_of_likes) # Prints 9, as expected
Почему book.num_of_likes
обновляется внутри delete_book_like
, но затем изменения не отображаются DeleteLikeView
?
Ответ №1:
book
В вашем представлении удаления это другой объект Python, чем instance.book
в вашем обработчике сигналов. Объект Python волшебным образом не узнает, что базовое представление БД изменилось. Вы могли бы вызвать refresh_from_db
перед печатью:
book.refresh_from_db()
print(book.num_of_likes)
Или просто создайте num_of_likes
динамически оцениваемое свойство в целом, и вам не придется беспокоиться о целостности ваших денормализованных данных:
class Book(models.Model):
@property
def num_of_likes(self):
return self.like_set.count()
Комментарии:
1. Спасибо за ваше решение. Не могли бы вы указать мне на некоторую документацию, касающуюся декоратора @property, который вы предложили? Спасибо
2. официальные документы всегда хорошее начало. Вас также может заинтересовать cached_property django