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 相关文章推荐
Flask SQLAlchemy一对一,一对多的使用方法实践
Feb 10 Python
Python中类的初始化特殊方法
Dec 01 Python
Python可变参数*args和**kwargs用法实例小结
Apr 27 Python
python绘制直线的方法
Jun 30 Python
Python面向对象之继承和组合用法实例分析
Aug 27 Python
Python通用循环的构造方法实例分析
Dec 19 Python
Python面向对象之继承和多态用法分析
Jun 08 Python
pytorch 批次遍历数据集打印数据的例子
Dec 30 Python
Python模块相关知识点小结
Mar 09 Python
Python 实现自动完成A4标签排版打印功能
Apr 09 Python
Flask模板引擎Jinja2使用实例
Apr 23 Python
Vs Code中8个好用的python 扩展插件
Oct 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
PHP多个版本的分析解释
2011/07/21 PHP
一个PHP的远程图片抓取函数分享
2013/09/25 PHP
QQ互联一键登录审核不通过的解决方案
2014/09/10 PHP
PHP转盘抽奖接口实例
2015/02/09 PHP
Yii2框架实现登陆添加验证码功能示例
2018/07/12 PHP
详解PHP PDO简单教程
2019/05/28 PHP
php校验公钥是否可用的实例方法
2019/09/17 PHP
Javascript typeof 用法
2008/12/28 Javascript
js 获取浏览器高度和宽度值(多浏览器)
2009/09/02 Javascript
JavaScript 监听textarea中按键事件
2009/10/08 Javascript
JavaScript实现x秒后自动跳转到一个页面
2013/01/03 Javascript
jQuery模拟超链接点击效果代码
2013/04/21 Javascript
JS定时器实例详细分析
2013/10/11 Javascript
JavaScript静态类型检查工具FLOW简介
2015/01/06 Javascript
jQuery插件pagewalkthrough实现引导页效果
2015/07/05 Javascript
jQuery增加和删除表格项目及实现表格项目排序的方法
2016/05/30 Javascript
javascript实现小型区块链功能
2019/04/03 Javascript
JavaScript实现省市联动效果
2019/11/22 Javascript
Vue.directive 实现元素scroll逻辑复用
2019/11/29 Javascript
JavaScript链式调用原理与实现方法详解
2020/05/16 Javascript
深入浅析Python字符编码
2015/11/12 Python
在java中如何定义一个抽象属性示例详解
2017/08/18 Python
python爬虫_实现校园网自动重连脚本的教程
2018/04/22 Python
利用python如何处理nc数据详解
2018/05/23 Python
详解程序意外中断自动重启shell脚本(以Python为例)
2019/07/26 Python
Python Pandas 如何shuffle(打乱)数据
2019/07/30 Python
如何用Python来理一理红楼梦里的那些关系
2019/08/14 Python
python实现logistic分类算法代码
2020/02/28 Python
Python Opencv中用compareHist函数进行直方图比较对比图片
2020/04/07 Python
详解pandas.DataFrame.plot() 画图函数
2020/06/14 Python
外企C语言笔试题
2013/11/10 面试题
一些网络技术方面的面试题
2014/05/01 面试题
小学教师节活动方案
2014/01/31 职场文书
教育学习自我评价
2014/02/03 职场文书
第二批党的群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
场地使用证明模板
2014/10/25 职场文书