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 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
#
Any ideas? Thank you. Juan
You get a QuerySet by using your model's Manager . Each model has at least one Manager , and it's called objects by default. Access it directly via the model class, like so: >>> Blog.objects <django.db.models.manager.Manager object at ...> >>> b = Blog(name='Foo', tagline='Bar') >>> b.objects Traceback: ...
This is because a Django QuerySet is a lazy object. It contains all of the information it needs to populate itself from the database, but will not actually do so until the information is needed.
Appending the annotate() clause onto a QuerySet lets you add an attribute to each item in the QuerySet, like if you wanted to count the amount of articles in each category. However, sometimes you only want to count objects that match a certain condition, for example only counting articles that are published.
Use Django's count() QuerySet method — simply append count() to the end of the appropriate QuerySet. Generate an aggregate over the QuerySet — Aggregation is when you "retrieve values that are derived by summarizing or aggregating a collection of objects." Ref: Django Aggregation Documentation.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With