【问题标题】:Why is my Django, jQuery, Ajax like button liking all posts?为什么我的 Django、jQuery、Ajax 按钮喜欢所有帖子?
【发布时间】:2020-08-14 05:45:41
【问题描述】:

我正在尝试在 Django ListView 中制作类似 Twitter 的社交媒体提要,并从 Django 3 By Example 书中添加了类似 Ajax 的按钮。类似的功能在 DetailView 中完美运行,但我无法让它在 ListView 中运行。当点击 DetailView 中的点赞按钮时,它会喜欢页面上的所有帖子,并且会显示 1 个喜欢,然后是 11110 个喜欢,然后从那里呈指数增长。 like/unlike 的切换是正确的,但不会将计数减 1;它只是不断上升。请帮忙!

模型.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'})

模板又名 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);
                } 
            }
        ); 
    });
});

【问题讨论】:

    标签: jquery django ajax django-templates


    【解决方案1】:

    似乎您正在选择 DOM 上的所有 a.like 元素,span.count.total 也是如此

    选择时应该更具体,最好使用 id。例如在&lt;a&gt;:

    <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 元素也是如此。请记住,您应该为每个元素使用 unique id,因此您可以附加 id="{{ post.id }}_like"id="{{ post.id }}_count"id="{{ post.id }}_total" 之类的后缀来区分。

    【讨论】:

    • 我的模板现在看起来像:&lt;span class="count" id="{{ post.id }}_count"&gt; &lt;span class="total" id="{{ post.id }}_total"&gt;{{ total_likes }}&lt;/span&gt; like{{ total_likes|pluralize }} &lt;/span&gt; &lt;a href="#" id="{{ post.id }}_like" data-id="{{ post.id }}" data-action="{% if request.user in users_like %}un{% endif %}like" class="like button"&gt;。那是对的吗?我已经尝试了您为我的 jQuery 建议的所有变体,但仍然没有运气。谢谢!
    • 我忽略了,但似乎id 不在成功后回调的范围内。我已经编辑了答案以反映一种可能的方法。希望对您有所帮助!
    • 尝试将喜欢的功能全部删除,并使页面重新加载到顶部....喜欢它跟随#的链接。还有其他建议吗?我将不胜感激。谢谢!
    • 没有更多细节很难调试,您是否尝试过查看控制台,检查哪个部分触发了页面重新加载?由于preventDefault,它应该跟随链接中的#,如果是这样,它不应该触发页面重新加载,可能会滚动到顶部。
    【解决方案2】:
    AJAX CODE 
    <script>
        $("a.btn-like").click(function(e){
            e.preventDefault();
            console.log("Button CLicked");
            var id = $(this).attr('data-id');
            console.log(id);
            mydata={
                id:id
            };
            mythis=this;
            $.ajax({
                type : 'GET',
                url : '{% url "like_post" %}',
                data : mydata,
                success : function(data){
                    console.log(data.likes);
                    $('#'+id).text(data.likes);
                }
            })
        })
    
    HTML
     <div class="container mb-5 mt-4">
          {% for p in posts %}
           <div class="card mx-auto mt-4 col-sm-8">
               <p class="display-6 lead">Title : {{p.title}}</p>
               <span class='p-2'>
                <a href="" id="btn-like" name='btn-like' data-id="{{p.id}}" value='{{p.id}}' class='text-decoration-none  mb-2 btn-like' ><span id="{{p.id}}">{{p.likes}}</span> 
                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-hand-thumbs-up mb-2" viewBox="0 0 16 16">
                        <path d="M8.864.046C7.908-.193 7.02.53 6.956 1.466c-.072 1.051-.23 2.016-.428 2.59-.125.36-.479 1.013-1.04 1.639-.557.623-1.282 1.178-2.131 1.41C2.685 7.288 2 7.87 2 8.72v4.001c0 .845.682 1.464 1.448 1.545 1.07.114 1.564.415 2.068.723l.048.03c.272.165.578.348.97.484.397.136.861.217 1.466.217h3.5c.937 0 1.599-.477 1.934-1.064a1.86 1.86 0 0 0 .254-.912c0-.152-.023-.312-.077-.464.201-.263.38-.578.488-.901.11-.33.172-.762.004-1.149.069-.13.12-.269.159-.403.077-.27.113-.568.113-.857 0-.288-.036-.585-.113-.856a2.144 2.144 0 0 0-.138-.362 1.9 1.9 0 0 0 .234-1.734c-.206-.592-.682-1.1-1.2-1.272-.847-.282-1.803-.276-2.516-.211a9.84 9.84 0 0 0-.443.05 9.365 9.365 0 0 0-.062-4.509A1.38 1.38 0 0 0 9.125.111L8.864.046zM11.5 14.721H8c-.51 0-.863-.069-1.14-.164-.281-.097-.506-.228-.776-.393l-.04-.024c-.555-.339-1.198-.731-2.49-.868-.333-.036-.554-.29-.554-.55V8.72c0-.254.226-.543.62-.65 1.095-.3 1.977-.996 2.614-1.708.635-.71 1.064-1.475 1.238-1.978.243-.7.407-1.768.482-2.85.025-.362.36-.594.667-.518l.262.066c.16.04.258.143.288.255a8.34 8.34 0 0 1-.145 4.725.5.5 0 0 0 .595.644l.003-.001.014-.003.058-.014a8.908 8.908 0 0 1 1.036-.157c.663-.06 1.457-.054 2.11.164.175.058.45.3.57.65.107.308.087.67-.266 1.022l-.353.353.353.354c.043.043.105.141.154.315.048.167.075.37.075.581 0 .212-.027.414-.075.582-.05.174-.111.272-.154.315l-.353.353.353.354c.047.047.109.177.005.488a2.224 2.224 0 0 1-.505.805l-.353.353.353.354c.006.005.041.05.041.17a.866.866 0 0 1-.121.416c-.165.288-.503.56-1.066.56z"/>
                      </svg>
                   </a>
               </span>
           </div>
          {% endfor %}
      </div>
    

    Python

    def like_post(request):
        id=request.GET.get('id')
        print(id)
        post=Post.objects.get(pk=id)
        post.likes+=1
        post.save()
        return JsonResponse({'likes':post.likes})
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 2012-09-20
    • 2011-09-22
    • 1970-01-01
    • 2019-11-07
    相关资源
    最近更新 更多