Обновление поля в методе сохранения другой модели с помощью F()
Я пытаюсь создать систему голосования, в которой оценка данного сообщения не зависит от типа голосов, отданных пользователями. В случае, если пользователь удаляет профиль, данный балл не должен увеличиваться/уменьшаться из-за того, что его голос был удален. Поэтому оценки обновляются только с помощью выражения F('score') + 1 или F('score') - 1.
Within Vote.save(), я пытаюсь реализовать это, но поле Question.score не обновляется при создании Vote. Как я могу получить тест, в котором оценка в вопросе изменяется от 0 до 1? django.db.models.F фактически импортируется в модуль, но не отображается здесь.
class TestQuestionScoreUpVote(TestCase):
'''Verify that a Question's score increments by one point
when the Vote is an "up" vote.'''
@classmethod
def setUpTestData(cls):
tag1 = Tag.objects.create(name="Tag1")
user = get_user_model().objects.create_user("TestUser")
profile = Profile.objects.create(user=user)
cls.question = Question.objects.create(
title="Question__001",
body="Content of Question 001",
profile=profile
)
cls.question.tags.add(tag1)
user_vote = Vote.objects.create(
profile=profile, type="upvote", content_object=cls.question
)
def test_new_user_vote_on_question(self):
self.assertEqual(self.question.score, 1)
class Post(Model):
body = TextField()
date = DateField(default=date.today)
comment = ForeignKey('Comment', on_delete=CASCADE, null=True)
profile = ForeignKey(
'authors.Profile', on_delete=SET_NULL, null=True,
related_name='%(class)ss',
related_query_name="%(class)s"
)
vote = GenericRelation(
'Vote', related_query_name="%(class)s"
)
score = IntegerField(default=0)
class Meta:
abstract = True
class Question(Post):
title = CharField(max_length=75)
tags = ManyToManyField(
'Tag', related_name="questions", related_query_name="question"
)
views = IntegerField(default=0)
objects = Manager()
postings = QuestionSearchManager()
class Meta:
db_table = "question"
ordering = ["-score" , "-date"]
def __repr__(self):
return f"{self.__class__.__name__}(title={self.title})"
class Vote(Model):
profile = ForeignKey(
'authors.Profile', on_delete=SET_NULL, null=True,
related_name="votes"
)
type = CharField(max_length=7)
content_type = ForeignKey(ContentType, on_delete=CASCADE)
object_id = PositiveIntegerField()
content_object = GenericForeignKey()
def save(self, *args, **kwargs):
post = ContentType.objects.get_for_id(
self.content_type_id
).get_object_for_this_type(id=self.object_id)
if self.type == "upvote":
post.score = F("score") + 1
else:
post.score = F("score") - 1
post.refresh_from_db()
super().save(*args, **kwargs)
Вы забываете вызвать post.save() после изменения объекта:
def save(self, *args, **kwargs):
post = ContentType.objects.get_for_id(
self.content_type_id
).get_object_for_this_type(id=self.object_id)
if self.type == "upvote":
post.score = F("score") + 1
else:
post.score = F("score") - 1
post.save() # <- HERE
post.refresh_from_db()
super().save(*args, **kwargs)