【问题标题】:Django: CSRF token missing or incorrectDjango:CSRF 令牌丢失或不正确
【发布时间】:2012-01-09 09:50:15
【问题描述】:

错误在位置http://127.0.0.1:8000/fileupload/form.py

我有 1.3 版的 django。我已尝试按照其他人的问题中所述指定 localhost:8000 ,但这对我不起作用。我正在尝试使用文件上传表单,但收到一个错误,即 form.py 没有 CSRF 令牌。

form.py:

class UploadFileForm(forms.Form):

    title = forms.CharField(max_length=50)
    file  = forms.FileField()

views.py:

def upload_file(request):

    c = {}
    c.update(csrf(request))

    if (not request.user.is_authenticated()) or (request.user == None):
      return HttpResponseRedirect("/?error=11")


    if request.method == 'POST':
      form = c['UploadFileForm'] = UploadFileForm(request.POST, request.FILES,  c, context_instance=RequestContext(request))

      if c['UploadFileForm'].is_valid():
        handle_uploaded_file(request.FILES['file'])
        return HttpResponseRedirect('/success/url/')

    else:
        form = c['UploadFileForm'] = UploadFileForm()
    return render_to_response('fileupload/upload.html', {'form': c['UploadFileForm']})

上传.html:

{% block main_content %}


  <form action="fileupload/form.py" enctype="multipart/form-data" method="POST">
    {% csrf_token %}
    <table>

      <tr><td>Title:</td><td><input type="text" name="title" /></td></tr>
      <tr><td>File:</td><td><input type="file" name="file" /></td></tr>
    </table>
      <input type="submit" value="Submit" class = "float_right button_input" />

  </form> 

{% endblock main_content %}

我很困惑,请告诉我一些要尝试的事情。谢谢你

【问题讨论】:

    标签: python django django-views


    【解决方案1】:

    对于我的情况,我使用 AJAX 将数据发布到我的视图函数,然后发生同样的错误,所以解决它的简单方法是更改​​数据

    data:{ 'k':'v' }
    

    data:{ 'k':'v' ,addcsrfmiddlewaretoken:'{{ csrf_token }}',}
    

    因为我们手动添加了一个csrf-token,所以它没有丢失或不正确。

    【讨论】:

      【解决方案2】:

      如果您使用 @cache_page(60 * 15) 装饰器,也会发生这种情况。如果您使用包含 CSRF 令牌的表单缓存页面,您将仅缓存第一个用户的 CSRF 令牌。所以有时调试起来有点困难。

      更多信息来自Django documentation

      如果 csrf_token 模板标签被模板(或 get_token 函数以其他方式调用),CsrfViewMiddleware 将添加一个 cookie 和响应的 Vary: Cookie 标头。这意味着 如果将中间件用作缓存中间件,它将与缓存中间件很好地配合使用 指示(UpdateCacheMiddleware 在所有其他中间件之前)。

      但是,如果您在单个视图上使用缓存装饰器,CSRF 中间件还不能设置 Vary 标头或 CSRF cookie,响应将被缓存,没有任何一个。在 在这种情况下,在任何需要插入 CSRF 令牌的视图上 你应该使用 django.views.decorators.csrf.csrf_protect() 装饰者优先:

      from django.views.decorators.cache import cache_page
      from django.views.decorators.csrf import csrf_protect
      
      @cache_page(60 * 15)
      @csrf_protect
      def my_view(request):
          ...
      

      【讨论】:

        【解决方案3】:

        我的回答类似于上面@Yugal Jindle 的回答。

        我使用的是 Django 1.10,我遇到了类似的问题,编辑后它对我有用

        return render_to_response(param1, param2)
        

        return render(request, param1, param2)
        

        附:确保在 settings.py 的 MIDDLEWARE 变量中有以下行

        'django.middleware.csrf.CsrfViewMiddleware'
        

        【讨论】:

          【解决方案4】:

          您需要在render_to_response 中为csrf_token 传递RequestContext

          为此:(views.py)

          from django.template import RequestContext
          
          ...
          
          return render_to_response('fileupload/upload.html', {'form': c['UploadFileForm']},  RequestContext(request))
          # Added RequestContext
          

          这会将 csrf 的令牌传递给模板。

          【讨论】:

          • 您已经在模板中使用了{% csrf_token %},所以应该可以。
          • 加上 RequestContext 我得到一个类型错误 __init__() got an unexpected keyword argument 'context_instance'
          • 谢谢你,我刚刚想通了。就像你说的那样添加 RequestContext(request) 并从 if 语句中删除 c 和 context_instance= 。如果您更改答案以包括我将其标记为正确。
          • 点击勾号接受答案有助于stackoverflow ;)
          猜你喜欢
          • 2013-01-12
          • 2014-07-12
          • 2018-10-23
          • 2017-09-09
          • 2011-12-26
          • 2014-03-29
          • 1970-01-01
          • 2021-07-14
          • 2021-11-13
          相关资源
          最近更新 更多