0

hi I have been making a social media site with a like feature similar to Instagram where user does not need to view the individual post to like it but can like that post directly from the main page , how can i do that ?

my main template:

{% load static %}

        {% if user.is_authenticated %}
        {% if obj %}
        <h1 style="background:skyblue;text-align:center;">Posts</h1>
            {% for obj in obj %}
            <div style="background:lightgrey;border-radius:5px;margin-bottom:20px;padding:1rem;">
                   <form method="get">
                       <input  hidden  value="{{obj.id}}" name="liked_post_id">
                   </form>

                <p>{{obj.user}}</p>
                <p>{{obj.name}}</p>
                <img height="250px" width="100%" src="{{  obj.image.url  }}" alt="Image ">
                <p>{{obj.desription}}</p>
<!--                {% include "like_page.html" %}-->
                <button id="btn_1"  name="btn_1" type="submit" value="{{ obj.id }}">like </button>
                <span id="like_count">{{obj.like_count}}</span>

                <h4>add a comment</h4>
                {% include "comments.html" %}
            </div>
            {% endfor %}

        {% else %}
        <h1 style="background:skyblue;text-align:center;">No Posts available</h1>
        {% endif %}
        {% endif %}

my urls :

from django.urls import path
from .views import index, show, LikeView, addComment\
    # , likeviewNumber


urlpatterns = [
    path("", index, name="home"),
    path("show", show, name="show"),
    path("like/", LikeView, name="post_like"),
    path("comment/",addComment, name="comment" ),
   # path('like_num',likeviewNumber )
]

the ajax I used:

 <script src="{% static 'jquery-3.6.0.js' %}" type="text/javascript"></script>
    <script>
        $(document).on('click','#btn_1',function(e){
            e.preventDefault();
          $.ajax({
            type:'POST',
            url:'{% url "post_like" %}',
            data:{
              postid:$('post_id').val(),  // idher mene abhi name=Post_id use kia ha <like_page.html> k ander  /warna yahan par buton ki id use hoti ha #btn_1
              csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
              action:'post'
            },
            success:function(json){
              document.getElementById("like_count").innerHTML=json['result']
              console.log(json)
            },
            error:function(xhr,errmsg,err){
           }
         });
})



 </script>

now my main problem is that I am showing all posts in a for loop and when the like button is clicked it contains the same id in each post but contains the individual unique post.id value but the ajax thinks I am clicking the very first button even when I like the last post I need a way to like each post from the main page like users post likes in Instagram without having to make a post details page please help .

sorry forgot to put the view i have been using ::

from django.shortcuts import render, HttpResponse, get_object_or_404
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login
from django.urls import reverse_lazy,reverse
from .models import Posts, Comments
from django.http import HttpResponseRedirect, JsonResponse
# Create your views here.

def LikeView(request):
    if request.POST.get('action') == 'post':
            # post_id = request.POST.get('post_id')
            result = ''
            id = request.POST.get('postid')
            post = get_object_or_404(Posts, id=id)
            if request.user in post.like.all():
                post.like.remove(request.user)
                post.like_count -= 1
                result = post.like_count
                post.save()
            else:
                post.like.add(request.user)
                post.like_count += 1
                result = post.like_count
                post.save()

            return JsonResponse({'result': result})

the model :

class Posts(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post_name = models.CharField(max_length=150)
    desription = models.CharField(max_length=200)
    image = models.ImageField(upload_to="images/uploads")
    like = models.ManyToManyField(User, related_name="liked", blank=True, default=None)
    # like_count = models.BigIntegerField(default=0)
    date_added = models.DateField(auto_now_add=True, blank=True)

    @property
    def like_count(self):
        return self.like.count()

    def __str__(self):
        return self.desription

    class Meta:
        db_table = "Posts"
        ordering = ["date_added"]
  • refer this https://dev.to/radualexandrub/how-to-add-like-unlike-button-to-your-django-blog-5gkg – Manoj Tolagekar Aug 24 '22 at 10:04
  • the writer of the post gave a Note at the top that the page will reload on each like click and that is the whole thing that I wanted to avoid , (reloading the page & having to make a post_detail.html) anyways thank you . – sameerAhmedjan Aug 24 '22 at 12:43

1 Answers1

1

You should use a class to trigger the AJAX action and then you can provide the ID of your post in a data- attribute like this :

<button class="likeBtn" data-post-id="{{ obj.id }}">like</button>
<span id="like_count{{ obj.id }}">{{obj.like_count}}</span>

And in your Javascript :

<script>
    $('.likeBtn').on('click', function() {
        $.ajax({
            type: 'POST',
            url: '{% url "post_like" %}',
            data: {
                postid: $(this).data('postId'),
                csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
                action:'post'
            },
            success: (json) => {
                $('#like_count' + $(this).data('postId')).html(json['result'])
                console.log(json)
            },
            error: (xhr, errmsg, err) => {
                console.error(xhr, errmsg, err)
            }
        })
    })
</script>
Benbb96
  • 1,973
  • 1
  • 12
  • 21
  • thank you for your answer , i will try this out but wouldn't it give each button the same class as the buttons are inside a loop ?? – sameerAhmedjan Aug 24 '22 at 12:36
  • Yes but it's ok to have the same class name, contrary to id. Notice that I changed that line `$(document).on('click','.likeBtn',function(e){` in order to execute the AJAX request every time a button with class `likeBtn` is clicked – Benbb96 Aug 24 '22 at 13:41
  • ok sure will try it out and check if it works , thank you – sameerAhmedjan Aug 24 '22 at 13:48
  • hi, I wanted to ask how can i see the span id correctly i have tried checking it in the log like this console.log($(this).data("post-id")) but is says undefined . I understand that you are wanting me to concatenate the post id with the span of each post so it only changes the like count on the current post , but I'm not able to check the span id – sameerAhmedjan Aug 25 '22 at 00:03
  • Oh yes, you're right. `$(this)` was undefined because of the `function` declaration. I've edited my answer to use arrow function instead. Now it should be working – Benbb96 Aug 25 '22 at 09:03
  • hi again , my problem was solved , and i was able to post likes directly , i was wondering what the function { $(this) } preforms in jQuery , because of it , the DOM did not care if i had multiple ids – sameerAhmedjan Aug 27 '22 at 07:55
  • You can check this answer to better understand : https://stackoverflow.com/a/12481556/8439435 What do you mean by "the DOM did not care if i had multiple ids" – Benbb96 Aug 28 '22 at 09:02