问答游戏后端如何有效更新总分?
How to update the total score in a trivia game backend efficiently?
我正在尝试在 Django 中实现问答游戏后端。我有几个模型,但我会提到其中两个,它们是 Score
和 Player
.
这里是Player
的重要部分:
class Player(BaseModel, AbstractUser):
overall_score = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['-overall_score']
这里是Score
的重要部分:
class Score(BaseModel):
score = models.PositiveSmallIntegerField()
player = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='scores')
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
self.player.overall_score += self.score
Score
和Player
中还有其他字段,但我没有提到它们。
我想做的是让玩家解决一个小测验,并将单个小测验分数保存到数据库后,我想计算所有时间的总分,即所有分数的总和他的分数。这只是一个总和,不是一个平均值。
我对保存方法的实现是否正确?
恐怕保存过程会因任何原因失败,但 overall_score
已经更新了。此外,我担心如果我使用聚合,这将不是一种有效的方法,因为每次用户访问排行榜时,都会计算总和,这可以通过保存总和来避免,因此我们避免每次对所有分数求和时间,我说的对吗?
编辑 1:
我尝试按照 Doodle 的建议使用信号来实现。但是,代码无法正常工作并给我一个错误:
TypeError: unsupported operand type(s) for +=: 'int' and 'DeferredAttribute'
这是我的signals.py
代码:
from django.db.models.signals import post_save
from django.dispatch.dispatcher import receiver
from .models import Score
@receiver(post_save, sender=Score)
def create_score(sender, instance, **kwargs):
instance.player.overall_score += instance.score
instance.player.save()
我尝试了多种方法来修复错误,但都无法解决。
您的 save()
方法不会保存 Score
对象或 player.overall_score
要做到这一点,需要:
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.player.overall_score += self.score
self.player.save()
请记住,如果分数对象被更新,它会不断将分数添加到玩家的总分中。例如
>>> player = Player()
>>> player.save()
>>> player.overall_score()
0
>>> score = Score(player=player, score=10, other_field='hey')
>>> score.save()
>>> player.overall_score()
10
>>> score.other_field = 'you'
>>> score.save()
>>> player.overall_score()
20
根据保存分数的方式,最佳设计可能会有所不同。玩家可以多次完成测验吗?新分数会不断添加到他们的总分中吗?或者他们只能完成一次测验吗?他们可以完成多次但每次测验只有一个分数吗?
我正在尝试在 Django 中实现问答游戏后端。我有几个模型,但我会提到其中两个,它们是 Score
和 Player
.
这里是Player
的重要部分:
class Player(BaseModel, AbstractUser):
overall_score = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['-overall_score']
这里是Score
的重要部分:
class Score(BaseModel):
score = models.PositiveSmallIntegerField()
player = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='scores')
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
self.player.overall_score += self.score
Score
和Player
中还有其他字段,但我没有提到它们。
我想做的是让玩家解决一个小测验,并将单个小测验分数保存到数据库后,我想计算所有时间的总分,即所有分数的总和他的分数。这只是一个总和,不是一个平均值。
我对保存方法的实现是否正确?
恐怕保存过程会因任何原因失败,但 overall_score
已经更新了。此外,我担心如果我使用聚合,这将不是一种有效的方法,因为每次用户访问排行榜时,都会计算总和,这可以通过保存总和来避免,因此我们避免每次对所有分数求和时间,我说的对吗?
编辑 1: 我尝试按照 Doodle 的建议使用信号来实现。但是,代码无法正常工作并给我一个错误:
TypeError: unsupported operand type(s) for +=: 'int' and 'DeferredAttribute'
这是我的signals.py
代码:
from django.db.models.signals import post_save
from django.dispatch.dispatcher import receiver
from .models import Score
@receiver(post_save, sender=Score)
def create_score(sender, instance, **kwargs):
instance.player.overall_score += instance.score
instance.player.save()
我尝试了多种方法来修复错误,但都无法解决。
您的 save()
方法不会保存 Score
对象或 player.overall_score
要做到这一点,需要:
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.player.overall_score += self.score
self.player.save()
请记住,如果分数对象被更新,它会不断将分数添加到玩家的总分中。例如
>>> player = Player()
>>> player.save()
>>> player.overall_score()
0
>>> score = Score(player=player, score=10, other_field='hey')
>>> score.save()
>>> player.overall_score()
10
>>> score.other_field = 'you'
>>> score.save()
>>> player.overall_score()
20
根据保存分数的方式,最佳设计可能会有所不同。玩家可以多次完成测验吗?新分数会不断添加到他们的总分中吗?或者他们只能完成一次测验吗?他们可以完成多次但每次测验只有一个分数吗?