0

I have a Django app where I want to display a page containing user posts which can be liked by other users by clicking on a Font Awesome Icon which futher is in an anchor tag. When a post is liked by a user, the icon class should be changed from fa-heart to fa-heart-o and vice-versa. To achieve this an Ajax request is made by the click event on the icon. This changes the icon and increments/decrements the like count.

I have this like FBV:

#feeds/views.py
@login_required
def like(request):
    post_id = request.GET.get("post_id", "")
    user = request.user
    post = Post.objects.get(pk=post_id)
    liked= False
    like = Like.objects.filter(user=user, post=post)
    if like:
        like.delete()
    else:
        liked = True
        Like.objects.create(user=user, post=post)
    resp = {
        'liked':liked
    }
    response = json.dumps(resp)
    return HttpResponse(response, content_type = "application/json")

And in urls.py :

urlpatterns=[
    path('like/', views.like, name='like'),
]

This is the template

{% for post in posts %}
......
</li>
<li>
    {% if post in liked_post %}
    <span class="like" data-toggle="tooltip" title="Unlike">
        <a href="{% url 'like' %}" id="like" post_id="{{ post.id }}"><i class="fa fa-heart"></i></a>
        <ins>{{ post.likes.count }}</ins>
    </span>
    </a>
    {% else %}
    <span class="like" data-toggle="tooltip" title="Like">
        <a href="{% url 'like' %}" id="like" post_id="{{ post.id }}"><i class="fa fa-heart-o"></i></a>
        <ins>{{ post.likes.count }}</ins>
    </span>
    </a>
    {% endif %}
</li>
...
{% endfor %}

This is the Ajax Call.

$('#like').click(function (e) {
    console.log('requested !')
    var _this = $(this);
    e.preventDefault();
    $.ajax({
        type: "GET",
        url: "{% url 'like' %}",
        data:{
            post_id: _this.attr('post_id')
        }
        success: function (res) {
            if (res.liked){
                icon = _this.find("i");
                icon.toggleClass("fa-heart fa-heart-o");
                console.log('liked');
            }
            else{
                icon = _this.find("i");
                icon.toggleClass("fa-heart-o fa-heart");
                console.log('unliked');
            }
        }
    });
});

Now the problem is : whenever I click the heart icon, the page gets redirected to /like(which I presume to not occur since there is a use of preventDefault();) and I cannot like the post. How could I solve that ? I have tried different solutions like these:

How to change icon using ajax call

Change anchor text and icon with jquery

How can I change an element's class with JavaScript?

Change the color of the icon in jquery (django project)

But none of these worked for me. So the question is how could I implement this ? Also, how can I change the likes count after a successful ajax call ?

1 Answers1

0

Give this a try

success: function (res) {
    if (res.liked){
        icon = _this.find("i");
        icon.removeClass();
        icon.addClass("fa-heart-o");
        console.log('liked');
    }
    else{
        icon = _this.find("i");
        icon.removeClass();
        icon.addClass("fa-heart");
        console.log('unliked');
    }

This will show fa-heart-o if the user liked the post and fa-heart if the user disliked the post.

Sumithran
  • 6,217
  • 4
  • 40
  • 54