开发者

django - how to get a queryset based on a count of references to foreign field

开发者 https://www.devze.com 2023-02-12 09:23 出处:网络
Question about how to perform a django query. I have a Game model with a \'through\' ManyToManyField to the User model.

Question about how to perform a django query. I have a Game model with a 'through' ManyToManyField to the User model.

class Game(models.Model):
    # other misc game-description fields...
    players = models.ManyToManyField(User, through='PlayerGameResult',
                                     blank=True, null=True)

class PlayerGameResult(models.Model):
    game            = models.ForeignKey(Game)
    player          = models.ForeignKey(User)
    dtime_played    = models.DateTimeField(default=datetime.now)
    # ...

If a particular game has been played by 1+ players, then the players field in the Game model will have 1+ references. Otherwise players is null. For the query question please refer to the ?????? below....

# all games not yet played b开发者_开发问答y this user...
games_qset = Game.objects.exclude(players__username=request.user.username)

# out of all the games not played by this user, extract the ones not
# yet played by anyone else either (this user would be the 1st player)
games_unplayed_qset = games_qset.filter(players__isnull=True)


# here's the question: out of all the games that have not been played by 
# this user, get a queryset that extracts only the games that have been 
# played by more than 10 (GAME_WITH_FEW_PLAYERS_THRESHOLD) players
# ?????? this is the query I don't know how to make... ?????
#
# in the following example, I want to get back a queryset that includes only
# Game Ids 6 and 19, because they have players count 20 and 12 (> threshold 10)
#
# (Pdb) for rec in games_qset: print rec
# Game id 6,  Num players:  20
# Game id 7,  Num players:   5
# Game id 13, Num players:   0
# Game id 19, Num players:  12
#
# for a count of all games that have been played by at least one player:
# (Pdb) games_qset.filter(players__isnull=False).count()
# 3
#

Any ideas? Thank you. Juan


It's confusing when you say "extract" as in exclude.

The answer is in annotation and aggregation.
http://docs.djangoproject.com/en/dev/topics/db/aggregation/

from django.db.models import Count
Games.objects.annotate(num_players=Count('players')).filter(num_players__gt=10)


I think you are looking for annotate - based on example in docs

q = Game.objects.filter(players__isnull=False).annotate(Count('players'))
q[0].players__count #prints first games players

or to filter by count

q = Game.objects.annotate(num_players=Count('players')).filter(num_players__gt=1)
0

精彩评论

暂无评论...
验证码 换一张
取 消