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 BeautifulSoup库抓取58手机维修信息
Nov 21 Python
python实现单线程多任务非阻塞TCP服务端
Jun 13 Python
解决python3中解压zip文件是文件名乱码的问题
Mar 22 Python
使用Python做定时任务及时了解互联网动态
May 15 Python
详解将Python程序(.py)转换为Windows可执行文件(.exe)
Jul 19 Python
python selenium 执行完毕关闭chromedriver进程示例
Nov 15 Python
基于python实现雪花算法过程详解
Nov 16 Python
django数据模型on_delete, db_constraint的使用详解
Dec 24 Python
python+selenium+PhantomJS抓取网页动态加载内容
Feb 25 Python
Python pandas如何向excel添加数据
May 22 Python
Python flask框架端口失效解决方案
Jun 04 Python
Python入门之使用pandas分析excel数据
May 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
整理的一些实用WordPress后台MySQL操作命令
2013/01/07 PHP
Php中用PDO查询Mysql来避免SQL注入风险的方法
2013/04/25 PHP
php面向对象的用户登录身份验证
2017/06/08 PHP
Extjs4 关于Store的一些操作(加载/回调/添加)
2013/04/18 Javascript
键盘上一张下一张兼容IE/google/firefox等浏览器
2014/01/28 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
2014/05/05 Javascript
JavaScript前端图片加载管理器imagepool使用详解
2014/12/29 Javascript
jquery操作select方法汇总
2015/02/05 Javascript
js实现仿Discuz文本框弹出层效果
2015/08/13 Javascript
深入学习JavaScript的AngularJS框架中指令的使用方法
2016/03/05 Javascript
使用递归遍历对象获得value值的实现方法
2016/06/14 Javascript
百度地图API之百度地图退拽标记点获取经纬度的实现代码
2017/01/12 Javascript
深入理解Vue.js源码之事件机制
2017/09/27 Javascript
vue.js element-ui validate中代码不执行问题解决方法
2017/12/18 Javascript
JavaScript实现删除数组重复元素的5种常用高效算法总结
2018/01/18 Javascript
js实现全选反选不选功能代码详解
2019/04/24 Javascript
nodejs log4js 使用详解
2019/05/31 NodeJs
webpack HappyPack实战详解
2019/10/08 Javascript
javascript 模块依赖管理的本质深入详解
2020/04/30 Javascript
OpenLayer3自定义测量控件MeasureTool
2020/09/28 Javascript
python实现折半查找和归并排序算法
2017/04/14 Python
通过Python 获取Android设备信息的轻量级框架
2017/12/18 Python
Python常见字符串操作函数小结【split()、join()、strip()】
2018/02/02 Python
python文本数据相似度的度量
2018/03/12 Python
详解python实现数据归一化处理的方式:(0,1)标准化
2019/07/17 Python
解决Python 写文件报错TypeError的问题
2020/10/23 Python
Python3 用什么IDE开发工具比较好
2020/11/28 Python
详解CSS3开启硬件加速的使用和坑
2017/08/21 HTML / CSS
css实例教程 一款纯css3实现的超炫动画背画特效
2014/11/05 HTML / CSS
英国电动工具购买网站:Anglia Tool Centre
2017/04/25 全球购物
《在家里》教后反思
2014/03/01 职场文书
一份文言文检讨书
2014/09/13 职场文书
党员批评与自我批评范文
2014/09/23 职场文书
学生偷窃检讨书
2014/09/25 职场文书
2015初中生物教研组工作总结
2015/07/21 职场文书
高二数学教学反思
2016/02/18 职场文书