1

I am stuck on a problem I am having trying to implement a 'Like' button into my django application.

I have the functionality working for the models, and even in the html template the code works if I manually add a like from a user.

It seems like my Ajax may be the issue, but I can't seem to figure out why.

Here is my models.py:

class Post(models.Model):
    direct_url = models.URLField(unique=True)
    post_url = models.URLField()
    post_title = models.CharField(max_length=300)
    time_posted = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

class Like(models.Model):
    liker = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='likes')
    date_created = models.DateTimeField(default=timezone.now)

    def save(self, *args, **kwargs):
        super(Like, self).save(*args, **kwargs)

And here is my views.py

class PostListView(LoginRequiredMixin, generic.ListView):
    model = Post
    template_name = 'homepage/home.html'
    ordering = ['-time_posted']
    context_object_name = 'posts'
    paginate_by = 6

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = datetime.now()
        context['likesbyuser'] = Like.objects.filter(liker=self.request.user)
        return context


def likePost(request):
    if request.method == 'GET':
        post_id = request.GET['post_id']
        likedpost = Post.objects.get(pk=post_id)  # getting the liked post

        if Like.objects.filter(post=likedpost, liker=request.user).exists():
            Like.objects.filter(post=likedpost, liker=request.user).delete()
        else:
            m = Like(post=likedpost, liker=request.user)  # creating like object
            m.save()  # saves into database
        return HttpResponse(likedpost.likes.count())
    else:
        return HttpResponse("Request method is not a GET")

This is part of the template, where I am putting the buttons to use the Ajax which should call the like function:

{% for i in post.likes.all %}
                    {% if user == i.liker %}
                            <a class='likebutton' data-catid="{{ post.id }}"><i id='like{{ post.id }}' class="btn fas fa-heart fa-lg post-buttons "></i></a>
                    {% elif forloop.last %}
                            <a class='likebutton' data-catid="{{ post.id }}"><i id='like{{ post.id }}' class="btn far fa-heart fa-lg post-buttons "></i></a>
                    {% endif %}

            {% empty %}
                    <a class='likebutton' data-catid="{{ post.id }}"><i id='like{{ post.id }}' class="btn far fa-heart fa-lg post-buttons "></i></a>

            {% endfor %}
{% endfor %}

And here is the Ajax code I am adding to the base.html in script tags.

<script type="text/javascript">
$('main').on('click', '.likebutton', function(){
    var catid;
    catid = $(this).attr("data-catid");
$.ajax(
{
    type:"GET",
    url: "/likepost/",
    data:{
        post_id: catid
    },
    success: function(data){

    if(data==0){
        $('.like' + catid).toggle();
        $('#like' + catid).toggleClass("far fas");
        $('#likecount' + catid).html('');
        console.log(data+'if');
    }

    else if(data==1){
        if($('.like' + catid).is(":hidden"))
        {
            $('.like' + catid).toggle();
        }

        $('#like' + catid).toggleClass("far fas");
        $('#likecount' + catid).html(data + ' like');
        console.log(data+'elseif');
    }
    else{

        $('#like' + catid).toggleClass("far fas");
        $('#likecount' + catid).html(data + ' likes');
        console.log(data+'else');
        }
    }

})
});
</script>

I have tried adding event.preventDefault(); to the ajax call, but that did not fix my issue.

1 Answer 1

1

I found the issue.

I was pointing the Ajax code at "main" as seen in the following snippet:

...
<script type="text/javascript">
$('main').on('click', '.likebutton', function(){
...

My issue was that I forgot to surround the block with the main tag when I ported this project over.

In my base.html I added the following code:

<main role="main" class="container h-100">
    {% block content %}
    {% endblock content %}
</main>

This fixed the issue.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.