python Django框架实现自定义表单提交


Posted in Python onMarch 25, 2016

除了使用Django内置表单,有时往往我们需要自定义表单。对于自定义表单Post方式提交往往会带来由CSRF(跨站请求伪造)产生的错误"CSRF verification failed. Request aborted."

本篇文章主要针对"表单提交"和"Ajax提交"两种方式来解决CSRF带来的错误

一、表单提交
Template:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>计算数字和</title>
</head>
<body>
  <form method="post" action="{%url 'Calculate' %}">
    {% csrf_token %}
    <label for="A"><input id="A" name="ValueA" type="text"></label>
    <label for="B"><input id="B" name="ValueB" type="text"></label>
    <input type="submit" value="开始计算">
  </form>
</body>
</html>

Views.py:

def Calculate(request):
  if request.POST:
    a=request.POST["ValueA"]
    b=request.POST["ValueB"]
    c=str(int(a)+int(b))
    return render_to_response('Result.html',{'result':c})
  else:
    return render_to_response('Calculation.html',context_instance=RequestContext(request))

需要注意:

(1)在<form>标签内添加{% csrf_token %},这样在表单提交的过程中,会产生"csrfmiddlewaretoken"标识去防止CSRF

(2)在Get请求页面时,需要添加context_instance=RequestContext(request) ,它和{% csrf_token %}配合使用,缺少一个都会出现上述错误,RequestContext 需要在 django.shortcuts 导入

(3)只有当表单以Post方式提交时,才需要验证CSRF,Get方式是不需要的

二、Ajax提交
同比与表单提交,Ajax提交需要进行额外的操作,Ajax提交时需要自己提供"csrfmiddlewaretoken"标识参数。我们除了需要引入JQuery外还需要引入一段JS代码

jQuery(document).ajaxSend(function(event, xhr, settings) {
  function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }
  function sameOrigin(url) {
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
      (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
      // or any other URL that isn't scheme relative or absolute i.e relative.
      !(/^(\/\/|http:|https:).*/.test(url));
  }
  function safeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }
 
  if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
    xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
  }
});

Template:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Ajax 提交</title>
  <script type="text/javascript" src="/static/jquery.js"></script>
  <script type="text/javascript">
    jQuery(document).ajaxSend(function(event, xhr, settings) {
  function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
      var cookies = document.cookie.split(';');
      for (var i = 0; i < cookies.length; i++) {
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }
  function sameOrigin(url) {
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
      (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
      // or any other URL that isn't scheme relative or absolute i.e relative.
      !(/^(\/\/|http:|https:).*/.test(url));
  }
  function safeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }
 
  if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
    xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
  }
});
  </script>
  <script type="text/javascript">
    $(function(){
       $.ajaxSetup({
          data:{csrfmiddlewaretoken: '{{ csrf_token }}'}
        });
        $("#Comment").click(function(){
          $.post('{% url 'AjaxRequest' %}',{"a":$("#A").val(),"b":$("#B").val()},function(data){
            $("#result").html(data);
          });
        });
    });
  </script>
</head>
<body>
  <label for="A"><input id="A" name="ValueA" type="text"></label>
  <label for="B"><input id="B" name="ValueB" type="text"></label>
  <input type="button" id="Comment" value="开始计算">
  <h1>计算的结果为:<span id="result"></span></h1>
</body>
</html>

View.py:

def AjaxRequest(request):
  if request.POST:
    a =request.POST["a"]
    b=request.POST["b"]
    c=int(a)+int(b)
    return JsonResponse(c,safe=False)
  else:
    return render_to_response('AjaxDemo.html',context_instance=RequestContext(request))

需要注意:

(1)在使用引入的JS代码后,需要添加如下代码,这样JS就可以自动帮我们生成"csrfmiddlewaretoken"标识,接下来你就可以使用$.post()了

$.ajaxSetup({
          data:{csrfmiddlewaretoken: '{{ csrf_token }}'}
        });

(2)context_instance=RequestContext(request) 并不是必须的

(3)Get请求不需要以上操作,直接使用$.get()即可
注:本文使用的Django1.8.3版本进行测试。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Python 相关文章推荐
Python datetime时间格式化去掉前导0
Jul 31 Python
Python实现简单的文件传输与MySQL备份的脚本分享
Jan 03 Python
浅谈Django学习migrate和makemigrations的差别
Jan 18 Python
python3获取两个日期之间所有日期,以及比较大小的实例
Apr 08 Python
Django 登陆验证码和中间件的实现
Aug 17 Python
pandas dataframe添加表格框线输出的方法
Feb 08 Python
python实现定时压缩指定文件夹发送邮件
Dec 22 Python
Python 中list ,set,dict的大规模查找效率对比详解
Oct 11 Python
Python实现把类当做字典来访问
Dec 16 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
May 15 Python
pycharm软件实现设置自动保存操作
Jun 08 Python
Python列表的深复制和浅复制示例详解
Feb 12 Python
python Django批量导入数据
Mar 25 #Python
python Django批量导入不重复数据
Mar 25 #Python
用Python实现斐波那契(Fibonacci)函数
Mar 25 #Python
Python基础教程之正则表达式基本语法以及re模块
Mar 25 #Python
详解Python使用simplejson模块解析JSON的方法
Mar 24 #Python
解决Python出现_warn_unsafe_extraction问题的方法
Mar 24 #Python
python 回调函数和回调方法的实现分析
Mar 23 #Python
You might like
火车头discuz6.1 完美采集的php接口文件
2009/09/13 PHP
yii实现图片上传及缩略图生成的方法
2014/12/04 PHP
PHP中使用正则表达式提取中文实现笔记
2015/01/20 PHP
php计划任务之验证是否有多个进程调用同一个job的方法
2015/12/07 PHP
PHP7.1新功能之Nullable Type用法分析
2016/09/26 PHP
thinkPHP5.0框架简单配置作用域的方法
2017/03/17 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
JQuery 构建客户/服务分离的链接模型中Table分页代码效率初探
2010/01/22 Javascript
使用Firebug对js进行断点调试的图文方法
2011/04/02 Javascript
js获取class的所有元素
2013/03/28 Javascript
JS去除数组重复值的五种不同方法
2013/09/06 Javascript
javascript dom追加内容实现示例
2013/09/21 Javascript
每天一篇javascript学习小结(属性定义方法)
2015/11/19 Javascript
JavaScript模板引擎Template.js使用详解
2016/12/15 Javascript
jQuery Easyui 下拉树组件combotree
2016/12/16 Javascript
js鼠标跟随运动效果
2017/03/11 Javascript
详解vue表单验证组件 v-verify-plugin
2017/04/19 Javascript
vue引入swiper插件的使用实例
2017/07/19 Javascript
Vue写一个简单的倒计时按钮功能
2018/04/20 Javascript
vue-router 手势滑动触发返回功能
2018/09/30 Javascript
angularJs中orderBy筛选以及filter过滤数据的方法
2018/09/30 Javascript
使用jquery模拟a标签的click事件无法实现跳转的解决
2018/12/04 jQuery
如何手动实现es5中的bind方法详解
2018/12/07 Javascript
微信小程序外卖选购页实现切换分类与数量加减功能案例
2019/01/15 Javascript
ES6知识点整理之函数对象参数默认值及其解构应用示例
2019/04/17 Javascript
vue keep-alive 动态删除组件缓存的例子
2019/11/04 Javascript
javaScript中indexOf用法技巧
2019/11/26 Javascript
vue制作抓娃娃机的示例代码
2020/04/17 Javascript
python算法学习之桶排序算法实例(分块排序)
2013/12/18 Python
python如何通过protobuf实现rpc
2016/03/06 Python
Python利用WMI实现ping命令的例子
2019/08/14 Python
python 读取二进制 显示图片案例
2020/04/24 Python
英国体育器材进口商店:UK Sport Imports
2017/03/14 全球购物
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
2015/02/22 面试题
同意迁入证明模板
2014/10/26 职场文书
2015年高二班主任工作总结
2015/05/25 职场文书