django错误 - Reason given for failure: CSRF cookie not set.

本文详细阐述了如何解决Django框架中CSRF验证失败导致的403 Forbidden错误,包括设置中间件、使用视图装饰器、正确处理表单提交以及配置模板标签等关键步骤。

今天练习django的form的提交。当提交表单的时候,出现了


Forbidden (403)

CSRF verification failed. Request aborted.

Help

Reason given for failure:

    CSRF cookie not set.
    

In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:

  • Your browser is accepting cookies.
  • The view function uses RequestContext for the template, instead of Context.
  • In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
  • If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.

You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.

You can customize this page using the CSRF_FAILURE_VIEW setting.


从网上查到很多人说

在settings.py里面的MIDDLEWARE_CLASSES 中加入

'django.middleware.csrf.CsrfResponseMiddleware',


但是我的问题还是依旧,可是很多人说他们的问题就是这样解决的。后来知道是因为他们用的是1.2的版本,而我用的1.4版本,

后来去到官网:

https://docs.djangoproject.com/en/1.2/ref/contrib/csrf/


参照它说的:

To enable CSRF protection for your views, follow these steps:

  1. Add the middleware'django.middleware.csrf.CsrfViewMiddleware' to your list ofmiddleware classes, MIDDLEWARE_CLASSES. (It should comebeforeCsrfResponseMiddleware if that is being used, and before anyview middleware that assume that CSRF attacks have been dealt with.)

    Alternatively, you can use the decoratordjango.views.decorators.csrf.csrf_protect on particular views youwant to protect (see below).

  2. In any template that uses a POST form, use the csrf_token tag insidethe <form> element if the form is for an internal URL, e.g.:

    <form action="" method="post">{% csrf_token %}

    This should not be done for POST forms that target external URLs, sincethat would cause the CSRF token to be leaked, leading to a vulnerability.

  3. In the corresponding view functions, ensure that the'django.core.context_processors.csrf' context processor isbeing used. Usually, this can be done in one of two ways:

    1. Use RequestContext, which always uses'django.core.context_processors.csrf' (no matter what yourTEMPLATE_CONTEXT_PROCESSORS setting). If you are usinggeneric views or contrib apps, you are covered already, since theseapps use RequestContext throughout.

    2. Manually import and use the processor to generate the CSRF token andadd it to the template context. e.g.:

      from django.core.context_processors import csrf
      from django.shortcuts import render_to_response
      
      def my_view(request):
          c = {}
          c.update(csrf(request))
          # ... view code here
          return render_to_response("a_template.html", c)
      

      You may want to write your own render_to_response wrapper thattakes care of this step for you.

The utility script extras/csrf_migration_helper.py can help to automate thefinding of code and templates that may need to be upgraded. It contains fullhelp on how to use it.

但是问题依旧,后来又看到另外一种方式在这个网站上:

o manually exclude a view function from being handled by either of the two CSRFmiddleware, you can use the csrf_exempt decorator, found in thedjango.views.decorators.csrf module. For example:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

Like the middleware, the csrf_exempt decorator is composed of two parts: acsrf_view_exempt decorator and a csrf_response_exempt decorator, foundin the same module. These disable the view protection mechanism(CsrfViewMiddleware) and the response post-processing(CsrfResponseMiddleware) respectively. They can be used individually ifrequired.

终于把这个问题解决了。


其实我是绕开了这个问题,因为django之所以引进CSRF是为了避免Cross Site Request Forgeries攻击,而上面的解决方法恰好禁止掉这个django的功能。所以日后还得仔细研究下,在不禁掉这个功能的前提下成功的提交表单。




转自:http://blog.youkuaiyun.com/huangxiansheng1980/article/details/7482591

<think>根据引用[1]中提供的insertRow方法定义,它返回一个Promise对象,因此可以使用.then()方法。但是,用户遇到的错误是`TypeError: deliveryTable.insertRow(...).then is not a function`,这表明在运行时,`insertRow`方法并没有返回一个Promise(可能是由于方法实现不同,或者上下文问题)。 然而,在用户提供的引用[4]中,我们看到vxe-grid的菜单点击事件处理中有提到插入行的方法名为`_InsertRow`和`insertForClipboard`,但没有直接提到`insertRow`的具体用法。另外,用户最后补充了`insertRow(data, successopt, failureopt, asyncopt) → {Promise}`的用法说明,说明该方法应该返回Promise。 因此,问题可能出现在`this.Table`类的`insertRow`方法并没有按照预期返回Promise。我们需要检查以下几点: 1. 确认`this.Table`类中的`insertRow`方法是否真的返回一个Promise对象。 2. 如果该方法支持回调函数和Promise两种方式,那么需要检查调用方式是否正确。 根据用户提供的函数签名`insertRow(data, successopt, failureopt, asyncopt) → {Promise}`,我们可以推断该方法可以接受多个参数,其中`successopt`和`failureopt`是可选的回调函数,`asyncopt`用于控制是否异步。但是,如果只传递一个参数(即`insertData`),则应该返回Promise。 但是,错误提示告诉我们,返回的不是一个Promise(因为没有then方法)。所以,我们可以尝试以下修改: ### 修改方案1:按照方法签名传递参数 如果我们确信该方法返回Promise,那么可能是传递参数的方式不对。根据签名,我们可以这样调用: ```javascript deliveryTable.insertRow(insertData, null, null, true) .then(...) .catch(...); ``` 这里,我们传递了三个额外的参数:两个null(分别对应success和failure回调)和一个true(表示异步操作),这样就会返回Promise。 ### 修改方案2:检查方法实现 如果修改参数后仍然不行,那么我们需要检查`insertRow`方法的实现。但是,由于我们无法看到实际代码,我们可以考虑以下替代方案: 使用回调函数的方式(如果支持的话): ```javascript deliveryTable.insertRow( insertData, (result) => { if (result?.type === 'success' && result?.data?.value === true) { console.log(`成功插入${insertData.length}条数据到deliveryTable`); } else { console.error(`插入deliveryTable失败:${result?.message || '未知原因'}`); } }, (error) => { console.error(`插入deliveryTable异常:${error.message}`); }, true // 如果需要异步的话 ); ``` ### 修改方案3:使用async/await 如果方法返回Promise,我们也可以用async/await重写: ```javascript async function insertDeliveryData() { const deliveryTable = new this.Table("Deliverytable"); if (insertData.length > 0) { try { const result = await deliveryTable.insertRow(insertData, null, null, true); if (result?.type === 'success' && result?.data?.value === true) { console.log(`成功插入${insertData.length}条数据到deliveryTable`); } else { console.error(`插入deliveryTable失败:${result?.message || '未知原因'}`); } } catch (error) { console.error(`插入deliveryTable异常:${error.message}`); } } } insertDeliveryData(); ``` ### 最终建议 由于用户提供的函数签名表明`insertRow`返回Promise,因此我们首先尝试传递正确的参数个数(4个参数)来确保返回Promise。 修改后的代码: ```javascript const deliveryTable = new this.Table("Deliverytable"); if (insertData.length > 0) { // 根据方法签名传递参数:data, successCallback, failureCallback, async // 如果不需要回调函数,则传递null,并设置async为true(如果需要异步) deliveryTable.insertRow(insertData, null, null, true) .then(result => { if (result?.type === 'success' && result?.data?.value === true) { console.log(`成功插入${insertData.length}条数据到deliveryTable`); } else { console.error(`插入deliveryTable失败:${result?.message || '未知原因'}`); } }) .catch(error => console.error(`插入deliveryTable异常:${error.message}`)); } ``` 如果这样修改后仍然报错,那么可能需要检查`Table`类的实现,确认`insertRow`方法是否真的返回Promise。或者,查看相关文档或源代码。 **注意:** 第三个参数`asyncopt`可能不是布尔值,而是其他类型(如字符串),具体需要查看文档。但是用户提供的签名中没有详细说明,所以这里假设为布尔值。 ### 总结修改步骤 1. 给`insertRow`方法传递四个参数:数据、成功回调(null)、失败回调(null)、异步标志(true) 2. 如果仍然不行,尝试只用两个参数(数据和一个包含所有选项的对象)调用,具体需要参照库的文档。 由于信息有限,我们只能根据提供的签名进行尝试。 ### 相关问题 1. 如何判断一个JavaScript函数是否返回Promise对象? 2. 在调用第三方库方法时,如何正确处理异步操作? 3. 当函数调用不符合预期时,有哪些调试技巧? </think>根据您提供的 `insertRow` 方法签名 `insertRow(data, successopt, failureopt, asyncopt) → {Promise}`,以下是修复代码的方案: ### 修改后的代码 ```javascript const deliveryTable = new this.Table("Deliverytable"); if (insertData.length > 0) { // 调用 insertRow 并正确处理返回的 Promise deliveryTable.insertRow(insertData) .then(result => { if (result?.type === 'success' && result?.data?.value === true) { console.log(`成功插入${insertData.length}条数据到deliveryTable`); } else { console.error(`插入失败: ${result?.message || '未知原因'}`); } }) .catch(error => { console.error(`插入异常: ${error.message}`); }); } ``` ### 关键修改说明 1. **参数传递**: - 根据方法签名 `insertRow(data, successopt, failureopt, asyncopt)`,我们只传递了必需的 `data` 参数 - 省略了可选参数 `successopt`, `failureopt` 和 `asyncopt`,让方法使用默认行为 2. **Promise 处理**: - 方法签名明确指出返回类型是 `{Promise}`,因此 `.then()` 和 `.catch()` 是合法的 - 保留了原有的结果处理逻辑,符合引用[1]中异步处理的模式[^1] 3. **错误处理优化**: - 在 `catch` 块中添加了更详细的错误日志 - 保持了对 `result` 对象的可选链操作(`?.`),避免空值异常 ### 可能的问题排查 如果修改后仍出现相同错误,建议检查以下方面: 1. **环境兼容性**: ```javascript // 检查 Table 类是否存在 console.log(typeof this.Table); // 应输出 "function" // 检查 insertRow 方法是否存在 console.log(typeof deliveryTable.insertRow); // 应输出 "function" // 验证 insertRow 返回类型 const testPromise = deliveryTable.insertRow([]); console.log(testPromise instanceof Promise); // 应输出 true ``` 2. **异步选项处理**: ```javascript // 如果问题持续,尝试显式设置 asyncopt 参数 deliveryTable.insertRow(insertData, null, null, true) .then(/* ... */) .catch(/* ... */); ``` 3. **Polyfill 支持**(针对旧浏览器): ```html <!-- 在 HTML 中添加 Promise polyfill --> <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script> ``` ### 备选方案(使用 async/await) ```javascript async function insertDeliveryData() { const deliveryTable = new this.Table("Deliverytable"); if (insertData.length > 0) { try { const result = await deliveryTable.insertRow(insertData); if (result?.type === 'success' && result?.data?.value) { console.log(`成功插入${insertData.length}条数据`); } else { throw new Error(result?.message || '插入操作未返回成功状态'); } } catch (error) { console.error(`插入异常: ${error.message}`); } } } // 调用异步函数 insertDeliveryData(); ``` ### 引用说明 1. 异步操作应始终处理 reject 情况(参考引用[1]中的 Promise 模式)[^1] 2. 复杂的异步操作推荐使用 async/await 提高可读性(参考引用[2]中的异步测试示例)[^2]
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值