简体   繁体   中英

django ajax like button with css classes

hello I have a post model which has a like(m2m) and user(forgeinkey) model field and Im trying to check if the request.user has liked the post and if they have, I should show them a red heart button else a blue heart should be shown, now since there are multiple posts and likes, Im looping through each like object to check if the request.user has liked it or not. Unfortunately for some reason, I couldn't implement a good logic and I see like button for every user. Some help would be appreciated.

Here's my model:

class post(models.Model):
    user = models.ForeignKey(User,default='' , related_name='has_liked', on_delete=models.CASCADE)
    caption = models.CharField(max_length=100)
    image = models.FileField(upload_to='images/', null=True, blank=True)
    video = models.FileField(upload_to='videos/', null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True)
    like = models.ManyToManyField(User, null=True, blank=True, default='')

The View:

@login_required
def usersfeed(request):
    users = User.objects.all()
    posts = post.objects.filter(Q(user__in=request.user.profile.friend.all()) | Q(user=request.user)).order_by('-created')
    comments = Comment.objects.all()
    status_form = StatusForm(request.POST)
    friend_requests = FriendRequest.objects.filter(to_user=request.user)
    friends = request.user.profile.friend.all()
    for i in posts:
        likes = i.like.all()
        print(likes)
        for like in likes:
            if like.username == request.user.username:
                if request.user:
                    Hasliked = True
                    print('liked')
                else:
                    Hasnotliked = True
                    print('not liked')
    context = {
        'Post':posts,
        'User':users,
        'form':PostForm(),
        'Profile':profile,
        'Form':CommentForm(),
        'Comment':comments,
        'Status':status_form,
        'fr':friend_requests,
        'friend':friends,
        'Hasliked':Hasliked,
        'Hasnotliked':Hasnotliked,
    }
    return render(request, 'social_media/feed.html', context=context)

The view for ajax like counter:

@login_required
def like_post(request):
    Post = get_object_or_404(post, id=request.GET.get('post_id'))
    cssClass = 'colorRed'
    if Post.like.filter(id=request.user.id).exists():
        Post.like.remove(request.user)
    else:
        Post.like.add(request.user)
    count = Post.like.count()
    users = Post.like.all() 
    user = []
    for i in users:
        user.append((i.username))
    response = {
        'count':count,
        'users':user,
        'cssClass':cssClass,
    }
    return JsonResponse(response)

The Html code:

{% for i in Post %}
<form action="{% url 'like_post' %}" class='like-submit' data-catid="{{ i.id }}" method="GET">
    <div class="like">
            {% if Hasliked == True %}
                <button id="likeBtn{{ i.id }}" class="likeClassBtn colorRed">
                    <i class="fas fa-heart"></i>
                </button>
            {% endif %}
            {% if Hasnotliked == True %}
                <button id="likeBtn{{ i.id }}" class="likeClassBtn">
                    <i class="fas fa-heart"></i>
                </button>                      
            {% endif %}
            <div class="show_likes">
            <span id="likes_count{{ i.id }}">{{ i.total_likes }}</span>
            <div class="username_liked">
                <div id="user-likes{{ i.id }}" class="user-likes">
                    {% for p in i.like.all %}
                    {{ p.username }}
                    {% endfor %}
                </div>
            </div>
            </div>
    </div>
</form>
{% endfor %}

<script>
    $(document).ready(function () {
            $(".like-submit").submit(function (event) {
                event.preventDefault()
                const url = $(this).attr('action');
                const catid = $(this).attr("data-catid");
                $.ajax({
                        type: "GET",
                        url: url,
                        data: {
                            post_id: catid,
                        },
                        success: function (data) {
                            $('#likes_count' + catid).html(data.count)
                            if ($('#user-likes' + catid).html()){
                                $('#user-likes' + catid).html(data.users + ' ')
                                $('#likeBtn' + catid).toggleClass(data.cssClass)
                            }
                        }
                });
            });
    });
</script>

you need to store the hasLiked/hasNotLiked in the post record for that user. The code above, implies that all posts are either liked or unliked. You also need to rethink the way you load your context- the current code is extremely inefficient. I would suggest to replace the Hasliked and Hasnotliked context entries with id arrays where each one will contains the ids of the posts that the current user liked/disliked. Then in the template do in check:

{% if i.id in Hasliked %}   
  <button id="likeBtn{{ i.id }}" class="likeClassBtn colorRed">
    <i class="fas fa-heart"></i>   
  </button> 
{% endif %} 
{% if i.id in Hasnotliked %}   
  <button id="likeBtn{{ i.id }}" class="likeClassBtn">
    <i class="fas fa-heart"></i>   
  </button>
{% endif %}

the hasliked, disliked can be loaded using your current setup:

    friends = request.user.profile.friend.all()
    for i in posts:
        likes = i.like.all()
        print(likes)
        for like in likes:
            if like.username == request.user.username:
                if request.user:
                    Hasliked.append(i.id)
                    print('liked')
                else:
                    Hasnotliked.append(i.id)
                    print('not liked')

This it would be extremely inefficient, the best way to si ur is to query the database directly, and simply returning the ids:

l_likedPosts = PostActions.objects.filter(user_id=l_currUser,
liked=True)
.values_list('post_id',flat=True) Hasliked = list(l_likedPosts)

The code above assumes that you have a table PostActions that contains at least the user_id, the post_id and the liked/disliked status. This is generally what the manytomany field does for you, behind the scenes, but using it takes too much freedom in more complicated data models.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM