Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Guled Ahmed
Guled Ahmed
12,806 Points

Implementing an Upvote System Question

Currently I'm in the process of extending the social network application with an upvote system, but I'm not quite sure how to fully implement this, and I was wondering if I can get some tips.

class Post(Model):
    timestamp = DateTimeField(default=datetime.datetime.now)
    user = ForeignKeyField(
        rel_model = User,
        related_name = 'posts'
    )
    name = TextField()
    content = TextField()
    upvotes = IntegerField(default=0)
    url = TextField()
    category = TextField()

    class Meta:
        database = DATABASE
        order_by = ('-timestamp',)

I added an upvote property to the Post class with a default value of 0 for each post. My first attempt included making a function that would update a posts upvote property given an id from a link, but that wouldn't have worked because when making the link, lets say you are already viewing the post, Jinja won't let you do -> <a href={{url_for('stream', post_id={{post.id}}}}

This simply won't work. If anyone also knows a strategy of how to detect if the user had already upvoted, please let me know.

-----------------------------------------------MAJOR EDIT---------------------------------------------------------- Ok so I figured out how to increment my posts upvote property, but now I am stuck on how to make sure the user doesn't upvote more than once, and to decrement the upvote property of the post if the user clicks the button again. Here is how I accomplished the upvoting thus far:

#stream.html
<div class="voting_bar">
        <a href="/vote/{{post.id}}"><img src="/static/img/upvote.png"></a>
        <p>{{post.upvotes}}</p>
      </div>

Here I give the user a link, (recall before this that there was a for loop that went through all the posts in our database). When the user clicks the link, I pass the posts's id to this route:

@app.route('/vote/<int:post_id>')
def upvote(post_id):
    posts = models.Post.select().where(models.Post.id == post_id)
    if posts.count() == 0:
        abort(404)
    post = models.Post.select().where(models.Post.id == post_id).get()
    query = models.Post.update(upvotes = (post.upvotes+1)).where(models.Post.id == post_id)
    query.execute()
    return redirect(url_for('index'))

Now the only problem is identifying the user, and making it so that if they press the button again, they will just simply remove the upvote (also need to avoid negative upvotes, *There will be no down vote system in this app)

Regards, Guled

2 Answers

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

Guled A. You'll have to use JavaScript for the AJAX part, of course. Have your view return JSON (or just a 200 with no content) and only access it through JavaScript. When you get back a 200, change the vote's display on the page.

I don't remember if Flask has the ability or not, but you might consider checking whether or not the view was requested via AJAX. If so, I'd make it so it worked with or without JavaScript. If the request is AJAX, send back JSON. If it's not, send back the redirect.

Guled Ahmed
Guled Ahmed
12,806 Points

Thank you for the tips Kenneth. I appreciate it. Also Flask does have that ability using the request module.

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

Make a new Upvote model. The model instance should know the Post it's pointing to and the User that cast the vote. Then you can check to see if the Upvote exists for that Post and User and, if it does, delete it.

Guled Ahmed
Guled Ahmed
12,806 Points

Hello Kenneth, thank you so much for the strategy, I actually figured it out last night, and helped out another student who had a near similar situation. Thank you so much for your input, and your wonderful courses.

Regards,

Guled

Guled Ahmed
Guled Ahmed
12,806 Points

Right now I'm looking forward to making my app more lively with Ajax, rather than making the user's browser to reload all the time. If I get stuck, I'll be sure to ask you for help. :)

Guled Ahmed
Guled Ahmed
12,806 Points

---Major Edit--- I got it fixed! :D

-- Old Post-- Kenneth, I discovered that there is something wrong with my logic for my upvoting system. So I managed to register another user into my app, and when I login with the original admin, the post can be incremented by 1 successfully. After the post's upvotes is equal to 1 by the admin. I login the second user, and I try upvoting the same post from before, but it decrements to 0. Can you check out my logic?

Guled Ahmed
Guled Ahmed
12,806 Points

Kenneth, my real question is with this implementation, how can you redo my upvote system, but with ajax? I noticed that every time I click my button, the page refreshes, and I think that this is a bad user experience. Is there any tips you can give me?