首页 > 解决方案 > 如何正确序列化?按下时,Ajax 会更新对象 forloop 中 django upvote 按钮的所有实例

问题描述

好的,所以我有一个索引页面,其中包含可以被赞成或反对的项目。问题是,当我对一项项目进行投票/反对时,页面上的所有项目都被赞成/反对,并且页面上所有按钮的外观都发生了变化,而不仅仅是被赞成/反对的一个对象。

谁能帮我正确序列化每个 for 循环对象?

我的索引页:

{% 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>

我的意见功能:

@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

标签: javascriptjquerydjangoajax

解决方案


除了使用for-loopfor 脚本,您还可以简单地使用jqueryclosest()find()方法来实现相同的目标。以下是您需要在django代码中进行的一些更改:

{% for post in posts %}
  <div> //<!--add this div-->
    <span id="post_{{forloop.counter}}" data-value="{{post.id}}"></span>
    <button class="vote_action" value="upvote_button"> + </i></button>
    //<!--add class here-->
    <span id="votes_{{forloop.counter}}" class="votes_points">{{post.points}}</span>                              
    <button class="vote_action" value="downvote_button"> - </button>
</div>
{% endfor %}

然后,在您的 jquery 代码中,每当您的按钮被单击时,使用closest()方法来获取最接近的div然后使用它找到span位置class="votes_points"并获取它id并使用split方法来获取值。使用{{forloop.counter}}它我们也可以轻松地获取postid值。因此,您的jquery代码将如下所示:

$('.vote_action').click(function(e) {
    //get closest div
      var selector = $(this).closest('div');
      var button = $(this).attr("value");
      //find class get id and split to get counter
      var counter =selector.find('.votes_points').attr('id').split('_')
      //get span data-value
      var postid = selector.find("span[id=post_"+counter[1]+"]").attr('data-value');
      
      console.log("postID-->"+postid+"Button-->"+button+"counter[1]-->"+counter[1])
      e.preventDefault();
      //your ajax
       $.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
          }
          //add response to votes_point
          selector.find('.votes_points').text(json['result'])
          //change button looks
          $("#uvb_"+counter[1]).addClass("disabled");
          $("#dvb_"+counter[1]).addClass("disabled");
        },
        error: function(xhr, errmsg, err) {}
      })
     
    })

演示代码(带演示数据):

$('.vote_action').click(function(e) {
//get closest div
  var selector = $(this).closest('div');
  var button = $(this).attr("value");
  //find class get id and split to get counter
  var counter =selector.find('.votes_points').attr('id').split('_')
  //get span data-value
  var postid = selector.find("span[id=post_"+counter[1]+"]").attr('data-value');
  
  console.log("postID-->"+postid+" || Button-->"+button+" ||   counter[1]-->"+counter[1])
  e.preventDefault();
  //your ajax
   $.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
      }
      //add response to votes_point
      selector.find('.votes_points').text(json['result'])
      //change button looks
      $("#uvb_"+counter[1]).addClass("disabled");
      $("#dvb_"+counter[1]).addClass("disabled");
    },
    error: function(xhr, errmsg, err) {}
  })
 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
  <span id="post_1" data-value="1"></span>
  <button class="vote_action" value="upvote_button"> +</button>

  <span id="votes_1" class="votes_points">15</span>
  <button class="vote_action" value="downvote_button"> - </button>
</div>
<div>
  <span id="post_2" data-value="2"></span>
  <button class="vote_action" value="upvote_button"> +</button>

  <span id="votes_2" class="votes_points">52</span>

  <button class="vote_action" value="downvote_button"> - </button>
</div>
<div>
  <span id="post_3" data-value="3"></span>
  <button class="vote_action" value="upvote_button"> +</button>

  <span id="votes_3" class="votes_points">52</span>

  <button class="vote_action" value="downvote_button"> - </button>
</div>


推荐阅读