简体   繁体   中英

Django for-loop activates view multiple times when a button is pressed

I've been working on something of a blog site and on it of course you would post things. I have an index.html where I have this:

{% for post in posts %} {% include "blog/featuredpost.html" %} {% endfor %}

I've also used Django pagination. Now, what I want to make is a like and dislike button which is reusable, meaning I would probably want it in "blog/featuredpost.html". So, that's what I've done.

<div class="row">
<div class="col-sm-5">
    <div id="divLikes" class="col-sm-6 bg-success text-center">
        Likes: {{ post.likes }}
    </div>
    <div id="divDislikes" class="col-sm-6 bg-danger text-center text-block">
        Dislikes: {{ post.dislikes }}
    </div>
</div>
{% if user.is_authenticated %}
<div>
    <div class="col-sm-2">
        <form id="like_form" action="" method="POST">
            {% csrf_token %}
            <button id="like_button" type="submit" value="vote" class="btn btn-success btn-sm btn-block">
                <span class="glyphicon glyphicon-thumbs-up" aria-hidden="true"></span> Like
            </button>
        </form>
    </div>
    <div class="col-sm-2">
        <button type="button" class="btn btn-danger btn-sm btn-block">
            <span class="glyphicon glyphicon-thumbs-down" aria-hidden="true"></span> Dislike
        </button>
    </div>
    <div class="col-sm-3">
        <button type="button" class="btn btn-warning btn-sm btn-block">
            <span class="glyphicon glyphicon-comment" aria-hidden="true"></span> Comment
        </button>
    </div>
</div>
{% endif %}


 <script type="text/javascript">
       //$('#like_button').click(function(){ }); 
/* The for cycle sends all the posts id that should appear on the page. 
It should send just the one on which the like button is clicked. */
$(document).on('submit', '#like_form', function(event) {
event.preventDefault();
$.ajaxSettings.traditional = true;
$.ajax({
    type: 'POST',
    url: '{% url "like" %}',
    dataType: 'json',
    data: {
        csrfmiddlewaretoken: '{{ csrf_token }}',
        LikeId: {{ post.id }},
    },
    success: function(response) {
        $('#divLikes').load(' #divLikes', function() { 
            /* It's important to add the space before #divLikes, I don't know why */
            $(this).children().unwrap()
        })
    }
});

})

views.py

def view_like(request):
# AJAX Like Button
if request.user.is_authenticated:
    if request.method == 'POST':
        likepostId = request.POST.get('LikeId', '')
        print(likepostId)
        likepost = get_object_or_404(Post, id=likepostId)

        print(likepost.title + " has " + str(likepost.likes))

        response_data = {}
        return JsonResponse(response_data)
else: 
    raise Http404

return 200

I currently have it so it would just print out certain things. On the front page it actually just replicates the html/css part due to the AJAX success function. How do I make the like button specifically know that I want a like on the certain post that I've clicked on? Because, as it is now, it just spams all of the id's of all the other posts on the page, in no particular order.

The problem is you have there a bunch of nodes with the same id ( #like_form and #like_button ), and you add event to all of them. It's not allowed to have multiple elements with the same value of id . Remove the attribute id from form , change the button 's id to class , and set its value to id of the post, ie.:

<button type="submit" value="{{ post.id }}" class="vote_button btn btn-success btn-sm btn-block">

then hook the event to the class .vote_button , and submit its value (so the data.LikeId in your ajax request will be something like $(event.target).val() ) to idenfity which post you voted one

edit:

the javascript will roughly look like this:

<script type="text/javascript">
$(".vote_button").click(function(event) {
    event.preventDefault();
    $.ajaxSettings.traditional = true;
    $.ajax({
        type: 'POST',
        url: '{% url "like" %}',
        dataType: 'json',
        data: {
            csrfmiddlewaretoken: '{{ csrf_token }}',
            LikeId: $(event.target).val(),
        },
        success: function(response) {
            /* I am not sure what is this supposed to do
               load() expects url as the first parameter, not a node
            */
            $('#divLikes').load('#divLikes', function() { 
                $(this).children().unwrap()
            })
        }
    });
});
</script>

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