【问题标题】:How to update the total score in a trivia game backend efficiently?如何有效地更新琐事游戏后端的总分?
【发布时间】:2019-07-24 14:52:39
【问题描述】:

我正在尝试在 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:+= 不支持的操作数类型:“int”和“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()

我尝试通过多种方式修复错误,但都无法解决。

【问题讨论】:

标签: django django-models django-aggregation


【解决方案1】:

正如你的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

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

【讨论】:

  • 用户不能多次完成同一个测验。一旦创建了乐谱实例,就无法修改它。你认为signals 是比覆盖save 方法更好的解决方案吗?
  • 就个人而言,除非绝对必要,否则我不会使用信号,因为代码被分解为多个文件,这使得它更难理解。覆盖 save 方法代码更少,更容易阅读,更容易理解和更容易测试。
猜你喜欢
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-22
  • 2013-01-31
相关资源
最近更新 更多