如何将csrf_token传递给jqgrid的editurl的post params?

时间:2011-06-25 05:40:00

标签: javascript python django jqgrid

我正在使用JqGrid和Django框架。那是JS:

      jQuery("#list").jqGrid({
        url:'{% url views.manage.devicesajax %}',
        datatype: 'json',
        mtype: 'GET',
        colNames:['DID', 'UDID', 'Owner', 'Name', 'First seen', 'Last seen'],
        colModel :[ 
          {name:'did', index:'did', width: 30, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'udid', index:'udid', width: 120, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_owner', index:'d_owner', width: 70, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_name', index:'d_name', editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_firstseen', index:'d_firstseen', width: 80}, 
          {name:'d_lastseen', index:'d_lastseen', width: 80}],
        pager: jQuery('#pager'),
        rowNum:20,
        rowList:[20,50,100],
        sortname: 'did',
        sortorder: "desc",
        multiselect: true,
        viewrecords: true,
        imgpath: 'themes/basic/images',
        caption: 'Devices list',
        height: 330,
        width: 1000,
        onSelectRow: function(id) {
            var id = $("#list").getRowData(id).message_id;
            message_id = id;
        },
        editurl: "{% url views.manage.deviceseditajax %}"
    });

当我在JqGrid中编辑行时,我从editurl得到错误:

  

禁止(403)   CSRF验证失败。请求中止。

这是因为csrf_token没有传递给其他数据的editurl。 如何将csrf_token添加到要编辑的POST请求中?

此代码完美运行(完整的jqgrid init):

     jQuery("#list").jqGrid({
        url:'{% url views.manage.devicesajax %}',
        datatype: 'json',
        mtype: 'GET',
        colNames:['DID', 'UDID', 'Owner', 'Name', 'First seen', 'Last seen'],
        colModel :[ 
          {name:'did', index:'did', width: 30, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'udid', index:'udid', width: 120, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_owner', index:'d_owner', width: 70, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_name', index:'d_name', editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_firstseen', index:'d_firstseen', width: 80}, 
          {name:'d_lastseen', index:'d_lastseen', width: 80}],
        pager: jQuery('#pager'),
        rowNum:20,
        rowList:[20,50,100],
        sortname: 'did',
        sortorder: "desc",
        multiselect: true,
        viewrecords: true,
        imgpath: 'themes/basic/images',
        caption: 'Devices list',
        height: 330,
        width: 1000,
        editurl: "{% url views.manage.deviceseditajax %}",
    });

      jQuery("#list").navGrid('#pager',{edit:true,add:true,del:true,search:true},
        {
            closeAfterEdit:true,
            reloadAfterSubmit:true,
            closeOnEscape:true,
            editData: {csrfmiddlewaretoken: '{{ csrf_token }}'}
        },
        {
            closeAfterAdd:true,
            reloadAfterSubmit:true,
            closeOnEscape:true,
            editData: {csrfmiddlewaretoken: '{{ csrf_token }}'}
        }, 
        {
            closeOnEscape:true,
            delData: {csrfmiddlewaretoken: '{{ csrf_token }}'}
        }, 
        {
         caption: "Search",
         Find: "Find",
         Reset: "Reset",
         sopt  : ['eq', 'cn'],
         matchText: " match",
         rulesText: " rules",
         closeAfterSearch: true,
         afterShowSearch: function ()
         {
             $('#reset_filter1_block').show();
         }
       }
      );

4 个答案:

答案 0 :(得分:3)

我不使用Django框架而不熟悉csrf_token,但在Google搜索后,您似乎需要在请求的HTTP标头中设置它:xhr.setRequestHeader('X-CSRF-Token', csrf_token);。要在jqGrid的情况下执行此操作,您可以使用loadBeforeSend事件处理程序:

loadBeforeSend: function(jqXHR) {
    // you should modify the next line to get the CSRF tocken
    // in any way (for example $('meta[name=csrf]').attr('content')
    // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
    var csrf_token = '<%= token_value %>'; // any way to get
    jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
}

请参阅here了解非常接近的问题。

更新:要在表单编辑使用情况下发布其他数据,您可以使用editData:editData:{csrfmiddlewaretoken:'&lt;%= token_value%&gt;' }。例如:

jQuery("#list").jqGrid('navGrid','#pager',{},
    { // Edit option (parameters of editGridRow method)
        recreateForm:true,
        reloadAfterSubmit:false,
        closeOnEscape:true,
        savekey: [true,13],
        closeAfterEdit:true,
        ajaxEditOptions: {
            beforeSend: function(jqXHR) {
                // you should modify the next line to get the CSRF tocken
                // in any way (for example $('meta[name=csrf]').attr('content')
                // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
                var csrf_token = '<%= token_value %>'; // any way to get
                jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
            }
        },
        editData: {
            csrfmiddlewaretoken: '<%= token_value %>'
        }
    },
    { // Add options (parameters of editGridRow method)
        recreateForm:true,
        reloadAfterSubmit:false,
        closeOnEscape:true,
        savekey: [true,13],
        closeAfterAdd:true,
        ajaxEditOptions: {
            beforeSend: function(jqXHR) {
                // you should modify the next line to get the CSRF tocken
                // in any way (for example $('meta[name=csrf]').attr('content')
                // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
                var csrf_token = '<%= token_value %>'; // any way to get
                jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
            }
        },
        editData: {
            csrfmiddlewaretoken: '<%= token_value %>'
        }
    }
);

我在这里放置了两种方式:设置'X-CSRF-Token'HTTP标头并发布csrfmiddlewaretoken参数。您可以在相应的实验后删除一种方法。

如果您对页面上的所有网格使用一些参数,则可以更好地更改默认值(有关详细信息,请参阅here

jQuery.extend(jQuery.jgrid.edit, {
    recreateForm:true,
    reloadAfterSubmit:false,
    closeOnEscape:true,
    savekey: [true,13],
    closeAfterAdd:true,
    closeAfterEdit:true,
    ajaxEditOptions: {
        beforeSend: function(jqXHR) {
            // you should modify the next line to get the CSRF tocken
            // in any way (for example $('meta[name=csrf]').attr('content')
            // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
            var csrf_token = '<%= token_value %>'; // any way to get
            jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
        }
    },
    editData: {
        csrfmiddlewaretoken: '<%= token_value %>'
    }
});

此设置对于“添加”和“编辑”表单都很常见。因此,您可以使用简化形式的navGrid

jQuery("#list").jqGrid('navGrid','#pager');

答案 1 :(得分:0)

检查你的cookies。 Django的CSRF还保存了一个cookie csrftoken,它与你在表单中使用的csrf_token具有相同的值。您可以使用任何Javascript cookie库来获取cookie并将其作为csrfmiddlewaretoken传递给POST请求。

答案 2 :(得分:0)

根据jqGrid documentation,您可以传递 postData 选项。 如果您使用的是jQuery Cookie plugin,则可以添加以下内容:

postData: {
    csrfmiddlewaretoken: $.cookie(CSRF_COOKIE_NAME)
},

到jqGrid的选项列表。

CSRF_COOKIE_NAME已设置在您的django应用程序settings.py中,默认情况下为“csrftoken”。

答案 3 :(得分:0)

我发现使用最新的JqGrid和Inline Edit提交简单的解决方案提交csrf_token以请求没有@csrf_exempt的POST django

onSelectRow: function(id){
     if(id && id!==lastSel){ 
        $(selector).restoreRow(lastSel); 
        lastSel=id; 
     }

     var editparameters = {
        extraparam: {csrfmiddlewaretoken: $('.token-data').data('token')},
        keys: true,
      };
     $(selector).jqGrid('editRow', id, editparameters);

}

例如,请参阅我的博文: http://yodi.polatic.me/jqgrid-inline-editing-integration-with-django-send-csrf-token/