I have a QuerySet that I wish to pass to a generic view for pagination:
links = Link.objects.annotate(votes=Count('vote')).order_by('-created')[:300]
This is my "hot" page which lists my 300 latest submissions (10 pages of 30 links each). I want to now sort this QuerySet by an algorithm that HackerNews uses:
(p - 1) / (t + 2)^1.5
p = votes minus submitter's initial vote
t = age of submission in hours
Now because applying this algorithm over the entire database would be pretty costly I am content with just the last 300 submissions. My site is unlikely to be the next digg/reddit so while scalability is a plus it is required.
My question is now how do I iterate over my QuerySet and sort it by the above algorithm?
For more information, here are my applicable models:
class Link(models.Model):
category = models.ForeignKey(Category, blank=False, default=1)
user = models.ForeignKey(User)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
url = models.URLField(max_length=1024, unique=True, verify_exists=True)
name = models.CharField(max_length=512)
def __unicode__(self):
return u'%s (%s)' % (self.name, self.url)
class Vote(models.Model):
link = models.ForeignKey(Link)
user = models.ForeignKey(User)
created = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return u'%s vote for %s' % (self.user, self.link)
Notes:
- I don't have "downvotes" so just the presence of a Vote row is an indicator of a vote or a particular link by a particular user.
EDIT
I think I have been overcomplicating things and found out a nifty little piece of code:
links = Link.objects.annotate(votes=Count('vote')).order_by('-created')[:300]
for link in links:
link.popularity = ((link.votes - 1) / (2 + 2)**1.5)
But for the life of me I cannot get that to translate to my templates:
{% for link in object_list %}
Popularity: {{ link.popularity }}
{% endfor %}
Why is it not showing up? I know popularity is working because:
print 'LinkID: %s - Votes: %s - Popularity: %s' % (link.id, link.votes, link.popularity)
returns what I'd expect in console.