Django 如何在琐事游戏后端高效地更新总分?

Django 如何在琐事游戏后端高效地更新总分?,django,django-models,django-aggregation,Django,Django Models,Django Aggregation,我正在尝试在Django中实现一个琐事游戏后端。我有几个模型,但我会提到其中的两个是分数和球员 以下是玩家的重要部分: 下面是分数的重要部分: 分数和球员还有其他方面,但我没有提到 我想做的是让玩家解决一个测验,在将单个测验分数保存到数据库后,我想计算所有时间的总分数,这是他所有分数的总和。这只是一个总数,不是平均数 我的save方法的实现正确吗 我担心保存过程会因任何原因而失败,但总的_分数已经更新。此外,我担心如果我使用聚合,这将不是一种有效的方法,因为每次用户访问排行榜时,都会计算出总和,

我正在尝试在Django中实现一个琐事游戏后端。我有几个模型,但我会提到其中的两个是分数和球员

以下是玩家的重要部分:

下面是分数的重要部分:

分数和球员还有其他方面,但我没有提到

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

我的save方法的实现正确吗

我担心保存过程会因任何原因而失败,但总的_分数已经更新。此外,我担心如果我使用聚合,这将不是一种有效的方法,因为每次用户访问排行榜时,都会计算出总和,而保存总和可以避免这一情况,因此我们避免每次对所有分数进行总和,对吗

编辑1: 我试着按照他的建议用信号来执行。但是,代码不起作用,给我一个错误:

TypeError:不支持+=:“int”和“DeferredAttribute”的操作数类型

这是我的signals.py代码:

我尝试了几种方法来修复错误,但我做不到。

你的保存方法不会保存分数对象或球员。总分数

为此,需要:

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

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

看一看,你会有一些想法,如果还需要,可以发表评论explanation@Doodle正如你所建议的,我用信号编辑了我的问题。但是,它不起作用。用户不能多次完成同一个测验。一旦创建了score实例,就无法对其进行修改。你认为signals比重写save方法更好吗?就我个人而言,除非我必须使用signals,否则我不会使用signals,因为代码被分解成多个文件,这使得它更难理解。重写save方法的代码更少、更易于阅读、更易于理解和测试。
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()
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