问答游戏后端如何有效更新总分?

How to update the total score in a trivia game backend efficiently?

我正在尝试在 Django 中实现问答游戏后端。我有几个模型,但我会提到其中两个,它们是 ScorePlayer.

这里是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

ScorePlayer中还有其他字段,但我没有提到它们。

我想做的是让玩家解决一个小测验,并将单个小测验分数保存到数据库后,我想计算所有时间的总分,即所有分数的总和他的分数。这只是一个总和,不是一个平均值。

我对保存方法的实现是否正确?

恐怕保存过程会因任何原因失败,但 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

根据保存分数的方式,最佳设计可能会有所不同。玩家可以多次完成测验吗?新分数会不断添加到他们的总分中吗?或者他们只能完成一次测验吗?他们可以完成多次但每次测验只有一个分数吗?