I am trying to implement a trivia game backend in Django. I have several models but I will mention two of them which are Score
and Player
.
Here is the important part of Player
:
class Player(BaseModel, AbstractUser):
overall_score = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['-overall_score']
and here is the important part of 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
There are other fields in Score
and Player
but I did not mention them.
What I am trying to do is letting the player to solve a quiz, and after saving the single quiz score to the database, I want to calculate the all-the-time overall score which is the sum of all of his scores. It is just a sum, not an average.
Is my implementation of save method correct?
I am afraid that the saving procedure will fail for any reason, but the overall_score
would be already updated. Also, I am afraid that if I used aggregation, it will not be an efficient way because every time the user will access the leaderboard, the sum will be calculated which can be avoided by saving the sum so we avoid summing all of the scores every time, am I right?
EDIT 1: I tried to implement with signals as suggested by Doodle. However, the code is not working and giving me an error which is:
TypeError: unsupported operand type(s) for +=: 'int' and 'DeferredAttribute'
Here is my code of 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()
I tried to fix the error in several ways but I couldn't.