Nader
Nader

Reputation: 77

Only Want a user to 'like' a comment once. My code is not working

I have Post model, that has a field likes_total on it. I only want a user to be able to like a post once, but the code for this in the view is not working. here is the code:

views.py

def like(request, post_id, group_id):
    group = get_object_or_404(Group, pk= group_id)
    post =  get_object_or_404(Post, pk= post_id)
    likers = []

    if request.method == 'POST':
        if request.user in likers:
            return render(request, 'groups/detail.html', {'group':group, 'error': "you have already liked this post"} )
        else:
            post.likes_total += 1
            post.save()
            likers.append(request.user)
            return redirect('/groups/' + str(group_id) )
        # post.save()
    else:
        return render(request, 'groups/detail.html', {'group':group})

this code seems right to me, cant tell what the problem is.. any help would be really appreciated!

Upvotes: 0

Views: 99

Answers (3)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

You define a list named likers in the like function. That means that each time someone calls the like function, you construct a new and empty list.

You could construct the list outside the function, but this will not help either. In fact the only data that you can consider persistent (the data that you can insert/modify/delete such that the next call sees this differences) is in the database.

As a result you should let the database store the people who like the post, by for example adding a ManyToManyField to the Post model that refers to the users that liked to post. So you should edit the model:

class Post(Model):

    likers = ManyToManyField(User)
    # some other fields
    likes_total = IntegerField()

Now we can add the user that likes the post to the many-to-many relation:

def like(request, post_id, group_id):
    group = get_object_or_404(Group, pk= group_id)
    post =  get_object_or_404(Post, pk= post_id)

    if request.method == 'POST':
        if request.user in post.likers.all():
            return render(request, 'groups/detail.html', {'group':group, 'error': "you have already liked this post"} )
        else:
            post.likes_total += 1
            post.likers.add(request.user)
            post.save()
            return redirect('/groups/' + str(group_id) )
    else:
        return render(request, 'groups/detail.html', {'group':group})

Another improvement that you can make is using reverse to generate urls, instead of constructing URLs yourself.

Upvotes: 0

agubelu
agubelu

Reputation: 408

Your likers list isn't persisted anywhere and it's always initialized to an empty list, so the request.user will never be in the list.

You should edit your model so that each of your Post objects have a list of users that liked it, and then you can persist, update and check that list to ensure that each user likes each post once at most.

Upvotes: 0

Damel Lambert-Powell
Damel Lambert-Powell

Reputation: 97

Every time your function is called you set likers to be empty. Instead it should be an attribute of the post.

Upvotes: 1

Related Questions