Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Sum related fields that belongs to the same FK, for every object

So I'm trying to get the sum of every score in all games related to the according player and how many game he has played

class Player(models.Model):
     name = models.CharField()

class Game(models.Model):
     points = models.IntegerField()
     user = models.ForeignKey(User, on_delete=models.CASCADE)

My desired output is:

{
    "name": "asdf",
    "total_points": "9999"
    "games_played": "12"
}

I thought I could do it getting a value list of my players then looking the sum of all games and count games played for every value on the list, but I don't know how to do it.

I know how to do it for an specific Player, but I want to get the entire list. I see this as a loop where every Player counts by its own.

Thanks

like image 242
kachus22 Avatar asked Sep 11 '25 00:09

kachus22


2 Answers

Your models.py seems like incomplete, So I'm assuming a there is a FK relationship between Player and Game as below

class Player(models.Model):
    name = models.CharField(max_length=200)


class Game(models.Model):
    points = models.IntegerField()
    user = models.ForeignKey(Player, on_delete=models.CASCADE)


You can fetch all summary of your DB by using a Group By query as below,

from django.db.models import Count, Sum, F

Game.objects.annotate(name=F('user__name')).values('name').annotate(games_played=Count('id'), total_points=Sum('points'))



Sample output will be like this,

 <QuerySet [{'name': 'name_1', 'games_played': 2, 'total_points': 6}, {'name': 'name_2', 'games_played': 1, 'total_points': 2}]>


QuerySet is a iterable similar to list. You can iterate over it if you want. Hence each of the item from the QuerySet be like this,

{'name': 'name_1', 'games_played': 2, 'total_points': 6}
like image 80
JPG Avatar answered Sep 12 '25 18:09

JPG


Assuming that Player has a User stored as .user, you could do something like:

from django.db.models import Sum

games = Game.objects.filter(user=player.user)
output = {
    'name': player.name,
    'total_points': games.aggregate(Sum('points')),
    'total_games': games.count()
}
like image 35
mattjegan Avatar answered Sep 12 '25 18:09

mattjegan