reddit style voting with django
Hay i need to hand implemeneting a voting system into a model.
I've had a huge helping hand from Mike DeSimone making this work in the first place, but i need to expand upon his work.
Here is my current code
View
def show_game(request):
game = Game.objects.get开发者_运维问答(pk=1)
discussions = game.gamediscussion_set.filter(reply_to=None)
d = {
'game':game,
'discussions':discussions
}
return render_to_response('show_game', d)
Template
<ul>
{% for discussion in discussions %}
{{ discussion.html }}
{% endfor %}
</ul>
Model
class GameDiscussion(models.Model):
game = models.ForeignKey(Game)
message = models.TextField()
reply_to = models.ForeignKey('self', related_name='replies', null=True, blank=True)
created_on = models.DateTimeField(blank=True, auto_now_add=True)
userUpVotes = models.ManyToManyField(User, blank=True, related_name='threadUpVotes')
userDownVotes = models.ManyToManyField(User, blank=True, related_name='threadDownVotes')
def html(self):
DiscussionTemplate = loader.get_template("inclusions/discussionTemplate")
return DiscussionTemplate.render(Context({
'discussion': self,
'replies': [reply.html() for reply in self.replies.all()]
}))
DiscussionTemplate
<li>
{{ discussion.message }}
{% if replies %}
<ul>
{% for reply in replies %}
{{ reply }}
{% endfor %}
</ul>
{% endif %}
</li>
As you can see we have 2 fields userUpVotes and userDownVotes on the model, these will calculate how to order the discussions and replies.
How would i implement these 2 fields to order the replies and discussions based on votes?
Any help would be great!
EDIT
I've added a method to my model called vote_difference
def vote_difference(self):
return int(self.userUpVotes.count()) - int(self.userDownVotes.count())
I can user this in my templates to get the current vote, however i cannot use this in my view.py file to order by this value, is there anyway to include this value in my view?
EDIT (2)
I've slowly getting there, i need to annotate 2 fields and do a calculation on them, however it seems that i cannot do basic maths calculation with annotate.
Any ideas?
discussions = game.gamediscussion_set.filter(reply_to=None).annotate( score= (Count('userUpVotes') - Count('userDownVotes')) ).order_by('-score')
You may want to consider denormalizing your model slightly by adding a vote_score
integer field.
Then all you have to do is override save()
to calculate the score using your vote_difference()
method.
That makes sorting much easier, and likely reduces the number of database calls you are making.
The reddit algorithm is based on the formula for calculating gravity. I found it from this website
Reddit Algorithm
let t = (t1 – epoch)
(where t1 is the time the post was made)
let x be the number of up votes minus the number of down votes.
Then,
let y be:
- 1 if there are more up votes than down votes,
- -1 If there are more down voets than up votes,
- 0 if there are the same number.
Now Let
z = max({x,1})
And We Have
ranking = C log10(z) + yt1
Where C is a constant (C = 45000).
I know this is not a direct answer to your question. But taking a peek into reddit's code may be very helpful. It helped me when I had to implement a semi-inteligent image cropping algorithm similar to reddit's.
I released a voting application called qhonuskan-votes, you can check it from here: https://github.com/miratcan/qhonuskan-votes
精彩评论