Reputation: 5378
I have some Django models that record people's listening habits (a bit like Last.fm), like so:
class Artist(models.Model):
name = models.CharField()
class Song(models.Model):
artist = models.ForeignKey(Artist)
title = models.CharField()
class SongPlay(models.Model):
song = models.ForeignKey(Song)
user = models.ForeignKey(User)
time = models.DateTimeField()
class User(models.Model):
# doesn't really matter!
I'd like to have a user page where I can show the top songs that they've listened to in the past month. What's the best way to do this?
The best I've come up with so far is:
SongPlay.past_month
.filter(user=user)
.values('song__title', 'song__id', 'song__artist__name')
.annotate(plays=Count('song'))
.order_by('-plays')[:20]
Above, past_month
is a manager that just filters plays from the last month. Assume that we've already got the correct user
object to filter by as well.
I guess my two questions are:
How can I get access to the original object as well as the plays
annotation?
This just gives me certain values, based on what I pass to values
. I'd much rather have access to the original object – the model has methods I'd like to call.
How can I group from SongPlay
to Artist
?
I'd like to show a chart of artists, as well as a chart of songs.
Upvotes: 3
Views: 5317
Reputation: 176780
You can use the same field in both values
and annotate
.
You have the primary key of the Song
object (you could just use song
instead of song__id
), so use
Song.objects.get(id=...)
For your second question, do a separate query with song__artist
as the field in values
and annotate
:
from django.db.models import Count
SongPlay.past_month
.filter(user=user)
.values('song__artist')
.annotate(plays=Count('song__artist'))
.order_by('-plays')[:20]
Upvotes: 6
Reputation: 894
agf has already showed you how to group by song_artist. What I would do to get the actual Song object is store it in memcached, or if the method you are calling is rather simplistic make it a static method or a class method. You might could also initialize a Song object with the data from the query and not actually save it to get access to this method. Might help to know the details of the methods you want to call from the Song object.
Upvotes: 0