OK so I have an index page with items that can be up or downvoted.
The issue is that when I upvote/downvote one item, all items on the page are upvoted/downvoted and the appearance of all buttons on the page all change instead of just the one object that was upvoted/downvoted.
Can anyone help me serialize each for loop object correctly?
my index page:
{% for post in posts %}
<span id="post_{{forloop.counter}}" data-value="{{post.id}}"></span>
<button class="vote_action" value="upvote_button"> + </i></button>
<span id="votes_{{forloop.counter}}">{{post.points}}</span>
<button class="vote_action" value="downvote_button"> - </button>
{% endfor %}
...
<script type="text/javascript">
// JQUERY - AJAX SCRIPT FOR voting
$(document).ready(function(){
{% for post in posts %}
$('.vote_action').click(function(e) {
var postid = document.getElementById('post_{{forloop.counter}}').getAttribute('data-value');
var button = $(this).attr("value");
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "vote" %}',
data: {
postid: postid,
csrfmiddlewaretoken: '{{ csrf_token }}',
action: 'postvote',
button: button,
},
success: function(json){
if (json.length < 1 || json == undefined) {
//empty
}
document.getElementById("votes_{{forloop.counter}}").innerHTML = json['result']
//change button looks
$("#uvb_{{forloop.counter}}").addClass("disabled");
$("#dvb_{{forloop.counter}}").addClass("disabled");
},
error: function(xhr, errmsg, err) {}
})
})
{% endfor %}
})
</script>
My views function:
@login_required
def post_vote(request):
if request.POST.get('action') == 'postvote':
# get information from request about what item id it is
id = int(request.POST.get('postid'))
# And also which button was pressed
button = request.POST.get('button')
post = Posts.objects.get(id=id)
if button == 'downvote_button':
if not post.voters.filter(id=request.user.id).exists():
post.voters.add(request.user)
post.votes +=1
post.points -=2
post.save()
elif button == 'upvote_button':
if not post.voters.filter(id=request.user.id).exists():
post.voters.add(request.user)
post.votes +=1
post.points +=2
post.save()
# return result
post.refresh_from_db()
result = post.points
return JsonResponse({'result':result})
pass
2
Answers
After the support given by @swati, I was able to get this working correctly as demonstrated below for anyone else having trouble with a similar issue.
All credit goes to @swati
HTML portion of the page:
The JS/AJAX Section of the page
Instead of using
for-loop
for script you can simply useclosest()
andfind()
method of jquery to achieve same .Here are some change you need to make in your django code :Then , in your jquery code whenever your button is clicked use
closest()
method to get the closestdiv
then using this find thespan
whereclass="votes_points"
and get itsid
and usesplit
method to get the{{forloop.counter}}
value.Using this we can easily getpostid
value also . So,your jquery code will look like below :Demo Code(with demo datas) :