django - 如何根据对外部字段的引用计数获取查询集

时间:2011-02-22 15:47:05

标签: django django-models

关于如何执行django查询的问题。 我有一个游戏模型 使用'through'MultipleToManyField 用户模型。

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)
    # ...

如果1位玩家玩过特定游戏, 那么Game模型中的玩家领域就会有 1个参考文献。否则玩家为空。有关查询问题,请参阅??????下面....

# all games not yet played by 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
#

有什么想法吗?谢谢。 涓

2 个答案:

答案 0 :(得分:35)

当你在“排除”中说“提取”时,这会令人困惑。

答案是注释和聚合 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)

答案 1 :(得分:4)

我认为您正在寻找annotate - 基于文档中的示例

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

或按计数过滤

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