views:

844

answers:

3

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')
+3  A: 

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).
Jon Winstanley
Hay, thanks for the reply, certainly adds some insite into how reddits works.However, you seem to have missed the point.My model has 2 fields (userUpVotes and userDownVotes), ill be working out the difference between these values to determine how to order my discussions. userUpVotes could have 8 users in there, where userDownVotes could have 2. So the final vote would be userUpVotes - userDownVotes, which in that case could be +6. Now i need help how to add up the userDownVotes and userUpVotes fields, and take them away from each other and order based on that.
dotty
See update for addition info.
dotty
Sorry for not relating the algorithm to Django, I felt like this information would help although I realised it did not answer the question.
Jon Winstanley
A: 

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.

Vasil
the downside is that it uses the pylons framework not the django one :(
dotty
A: 

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.

Chris Lawlor