Почему моей Django, jQuery, Ajax кнопка лайка нравится все сообщения? - PullRequest
0 голосов
/ 30 апреля 2020

Я пытаюсь создать твиттер, похожий на ленту социальных сетей, в Django ListView и добавил кнопку Ajax как в книге Django 3 By Example . Подобная функция прекрасно работает в DetailView, но я не могу заставить ее работать в ListView. При нажатии кнопки «Нравится» в DetailView ему нравятся все сообщения на странице, и они показывают 1 лайк, затем 11110 лайков, а затем экспоненциально возрастает. Переключение «нравится / не похоже» является правильным, но не уменьшает счет на 1; это просто продолжает расти. Пожалуйста, помогите!

Models.py:

class Post(models.Model):
    content = models.TextField(max_length=150, blank=True)
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    image = models.ImageField(storage=PrivateMediaStorage(), upload_to = pics_path, blank=True, null=True)
    vid = models.FileField(storage=PrivateMediaStorage(), upload_to = vids_path, blank=True, null=True)
    users_like = models.ManyToManyField(User, related_name='posts_liked', blank=True)

Views.py:

@require_POST
def post_like(request):
    post_id = request.POST.get('id') 
    action = request.POST.get('action') 
    if post_id and action:
        try:
            post = Post.objects.get(id=post_id) 
            if action == 'like':
                post.users_like.add(request.user) 
            else:
                post.users_like.remove(request.user) 
            return JsonResponse({'status':'ok'})
        except: 
            pass
    return JsonResponse({'status':'ko'})

Шаблон aka post_list. html:

{% with total_likes=post.users_like.count users_like=post.users_like.all %}
    <div class="post-info"> 
        <div>
            <span class="count">
            <span class="total">{{ total_likes }}</span>
            like{{ total_likes|pluralize }}
            </span>
            <a href="#" data-id="{{ post.id }}" data-action="{% if request.user in users_like %}un{% endif %}like" class="like button">
            {% if request.user not in users_like %} 
            Like
            {% else %}
            Unlike
            {% endif %}
            </a>
        </div>
    </div>
{% endwith %}

jQuery:

    var csrftoken = Cookies.get('csrftoken'); 
    function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
    }
    $.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) { 
        xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }   
    }
});
$(document).ready(function(){
    $('a.like').click(function(e){
        e.preventDefault();
            $.post('{% url "like" %}',
                {
                    id: $(this).data('id'), 
                    action: $(this).data('action')
                },
                function(data){
                    if (data['status'] == 'ok') 
                    {
                    var previous_action = $('a.like').data('action');
                    // toggle data-action
                    $('a.like').data('action', previous_action == 'like' ? 'unlike' : 'like');
                    // toggle link text
                    $('a.like').text(previous_action == 'like' ? 'Unlike' : 'Like');
                    // update total likes
                    var previous_likes = parseInt($('span.count .total').text()); 
                    $('span.count .total').text(previous_action == 'like' ? previous_likes + 1 : previous_likes - 1);
                } 
            }
        ); 
    });
});

1 Ответ

0 голосов
/ 30 апреля 2020

Похоже, что вы выбираете все a.like элементы в DOM, то же самое для span.count.total

Вы должны быть более точными c при выборе, в идеале, используя id. Например, в <a>:

<a href="#" id="{{ post.id }}" data-id="{{ post.id }}" data-action="{% if request.user in users_like %}un{% endif %}like" class="like button">

Затем в jQuery:

$(document).ready(function(){
    $('a.like').click(function(e){
        e.preventDefault();
            var id = $(this).data('id');
            var action = $(this).data('action');
            $.post('{% url "like" %}',
                {
                    id: id, 
                    action: action
                },
                function(data){
                    if (data['status'] == 'ok') 
                    {
                    var previous_action = $('#' + id').data('action');
                    // toggle data-action
                    $('#' + id).data('action', previous_action == 'like' ? 'unlike' : 'like');
                    // toggle link text
                    $('#' + id).text(previous_action == 'like' ? 'Unlike' : 'Like');
                    // update total likes
                    var previous_likes = parseInt($('span.count .total').text()); 
                    $('#' + id + '_total').text(previous_action == 'like' ? previous_likes + 1 : previous_likes - 1);
                } 
            }
        ); 
    });
});

То же самое для элементов span. Помните, что вы должны использовать уникальный идентификатор для каждого элемента, поэтому, возможно, вы могли бы добавить суффикс, например id="{{ post.id }}_like", id="{{ post.id }}_count", id="{{ post.id }}_total" для дифференциации.

...