【问题标题】:Django -- Forbidden (CSRF token missing or incorrect.): /vote/Django -- 禁止(CSRF 令牌丢失或不正确。):/vote/
【发布时间】:2020-12-24 10:50:59
【问题描述】:

我有一个网站,帖子上有一个 AJAX 赞成或反对选项。 我遇到的问题是投票在我的帖子详细信息页面上有效,但在我的索引页面上无效。我收到错误Forbidden (CSRF token missing or incorrect.): /vote/

两个页面调用相同的视图和 URL 模式。

index.html:

{% 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">{{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: $('input[name=csrfmiddlewaretoken]').val(),
              action: 'postvote',
              button: button,
            },
            success: function(json){
              if (json.length < 1 || json == undefined) {
                //empty
              }
              document.getElementById("votes").innerHTML = json['result']
            },
            error: function(xhr, errmsg, err) {}
          })
        })
        {% endfor %}
      })
      </script>

post_detail.html:

    <span id="vote_id" data-value="{{post.id}}"></span>
    <button class="vote_action" value="upvote_button"> + </i></button>
    <span id="votes">{{post.points}}</span>                           
    <button class="vote_action" value="downvote_button"> - </button>

    <script type="text/javascript">
       // JQUERY - AJAX SCRIPT FOR voting
       $(document).ready(function(){
          $('.vote_action').click(function(e) {
              var postid = document.getElementById('vote_id').getAttribute('data-value');
              var button = $(this).attr("value");
              e.preventDefault();
              $.ajax({
                type: 'POST',
                url: '{% url "vote" %}',
                data: {
                  postid: postid,
                  csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
                  action: 'postvote',
                  button: button,
                },
                success: function(json){
                  if (json.length < 1 || json == undefined) {
                    //empty
                  }
                  document.getElementById("points").innerHTML = json['result']
                },
                error: function(xhr, errmsg, err) {}
              })
            })
          })
        </script>

urls.py

urlpatterns = [
    path('vote/', views.post_vote, name='vote' ),
]

views.py

@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

对不起,有史以来最长的帖子!我试图尽可能减少并留下基本信息。 有人有什么想法吗?

【问题讨论】:

  • 这两个页​​面是否具有相同的基本 URL?
  • 索引页面和帖子详细信息页面都有单独的 URL 模式,如果这就是您的意思的话。
  • 那么问题是您的浏览器会保护您免受交叉引用源的侵害。您将需要允许在标题中指定的交叉引用原点。见:stackoverflow.com/questions/10636611/…
  • 感谢您的回答。你认为在 Django 中最直接的方法是什么?
  • 我不是 Django 专家,但这似乎是一个很好的阅读来源:pypi.org/project/django-cors-headers

标签: django ajax django-csrf


【解决方案1】:

我现在似乎可以使用我在另一个 post 上遇到的以下方法。

在 index.html 中我已更改:

csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),

csrfmiddlewaretoken: '{{ csrf_token }}',

我不确定这是否是解决此问题的正确方法,并且必须等待网站最终上线时它是否有效。 欢迎任何意见。

【讨论】:

  • 这种方式是合法的。
猜你喜欢
  • 2019-11-24
  • 2021-01-08
  • 2015-10-15
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
  • 2016-05-08
  • 2019-02-21
  • 2020-06-16
相关资源
最近更新 更多