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 相关文章推荐
一则python3的简单爬虫代码
May 26 Python
Python里隐藏的“禅”
Jun 16 Python
浅谈python中截取字符函数strip,lstrip,rstrip
Jul 17 Python
python读取文本中数据并转化为DataFrame的实例
Apr 10 Python
利用anaconda保证64位和32位的python共存
Mar 09 Python
python Tcp协议发送和接收信息的例子
Jul 22 Python
python识别文字(基于tesseract)代码实例
Aug 24 Python
详解在python操作数据库中游标的使用方法
Nov 12 Python
Python:slice与indices的用法
Nov 25 Python
Python 统计位数为偶数的数字代码详解
Mar 15 Python
自学python用什么系统好
Jun 23 Python
基于Python实现将列表数据生成折线图
Mar 23 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
fleaphp下不确定的多条件查询的巧妙解决方法
2008/09/11 PHP
php str_pad 函数用法简介
2009/07/11 PHP
Yii学习总结之安装配置
2015/02/22 PHP
[原创]php获取数组中键值最大数组项的索引值
2015/03/17 PHP
PHP论坛实现积分系统的思路代码详解
2020/06/01 PHP
转一个日期输入控件,支持FF
2007/04/27 Javascript
THREE.JS入门教程(2)着色器-上
2013/01/24 Javascript
js清空表单数据的两种方式(遍历+reset)
2014/07/18 Javascript
JavaScript实现判断图片是否加载完成的3种方法整理
2015/03/13 Javascript
javascript背景时钟实现方法
2015/06/18 Javascript
JavaScript实现添加及删除事件的方法小结
2015/08/04 Javascript
JS实现的文字与图片定时切换效果代码
2015/10/06 Javascript
js仿iphone秒表功能 计算平均数
2017/01/11 Javascript
详解基于Angular4+ server render(服务端渲染)开发教程
2017/08/28 Javascript
web前端vue filter 过滤器
2018/01/12 Javascript
详解为什么Vue中不要用index作为key(diff算法)
2020/04/04 Javascript
jQuery实现动态向上滚动
2020/12/21 jQuery
Django查找网站项目根目录和对正则表达式的支持
2015/07/15 Python
python简单实现刷新智联简历
2016/03/30 Python
机器学习python实战之手写数字识别
2017/11/01 Python
Python实现的拟合二元一次函数功能示例【基于scipy模块】
2018/05/15 Python
python添加菜单图文讲解
2019/06/04 Python
pandas.DataFrame的pivot()和unstack()实现行转列
2019/07/06 Python
Python实现滑动平均(Moving Average)的例子
2019/08/24 Python
python实现PolynomialFeatures多项式的方法
2021/01/06 Python
美国乡村商店:Plow & Hearth
2016/09/12 全球购物
印尼第一大家居、生活和家具电子商务:Ruparupa
2019/11/25 全球购物
安全生产先进个人材料
2014/02/06 职场文书
个性发展自我评价
2014/02/11 职场文书
义务教育学校标准化建设汇报材料
2014/08/16 职场文书
学习走群众路线心得体会
2014/11/05 职场文书
学习保证书
2015/01/17 职场文书
2015年党风廉政建设工作总结
2015/04/09 职场文书
开学第一周总结
2015/07/16 职场文书
小学运动会入场口号
2015/12/24 职场文书
浅析MongoDB之安全认证
2021/06/26 MongoDB