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基于PycURL实现POST的方法
Jul 25 Python
详解Python中的from..import绝对导入语句
Jun 21 Python
python自带的http模块详解
Nov 06 Python
Python制作刷网页流量工具
Apr 23 Python
教你使用python实现微信每天给女朋友说晚安
Mar 23 Python
对numpy中数组元素的统一赋值实例
Apr 04 Python
对python中矩阵相加函数sum()的使用详解
Jan 28 Python
python3 批量获取对应端口服务的实例
Jul 25 Python
DataFrame.groupby()所见的各种用法详解
Jun 14 Python
用Python进行websocket接口测试
Oct 16 Python
python 多线程中join()的作用
Oct 29 Python
python unittest单元测试的步骤分析
Aug 02 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读写文件的方法(生成HTML)
2006/11/27 PHP
php eval函数用法 PHP中eval()函数小技巧
2012/10/31 PHP
在Mac上编译安装PHP7的开发环境
2015/07/28 PHP
超级退弹代码
2008/07/07 Javascript
JQuery困惑—包装集 DOM节点
2009/10/16 Javascript
一些相见恨晚的 JavaScript 技巧
2010/04/25 Javascript
JavaScript高级程序设计 事件学习笔记
2011/09/10 Javascript
jQuery循环滚动展示代码 可应用到文字和图片上
2012/05/11 Javascript
JQuery插件iScroll实现下拉刷新,滚动翻页特效
2014/06/22 Javascript
Jquery选择器中使用变量实现动态选择例子
2014/07/25 Javascript
jQuery实现带延迟的二级tab切换下拉列表效果
2015/09/01 Javascript
jQuery入门之层次选择器实例简析
2015/12/11 Javascript
JS简单实现移动端日历功能示例
2016/12/28 Javascript
jQuery插件zTree实现更新根节点中第i个节点名称的方法示例
2017/03/08 Javascript
详解node+express+ejs+bootstrap构建项目
2017/09/27 Javascript
Vue 配合eiement动态路由,权限验证的方法
2018/09/26 Javascript
微信小程序音乐播放器开发
2019/11/20 Javascript
react国际化化插件react-i18n-auto使用详解
2020/03/31 Javascript
Python Django使用forms来实现评论功能
2016/08/17 Python
python 读取DICOM头文件的实例
2018/05/07 Python
Pandas 同元素多列去重的实例
2018/07/03 Python
Python实现爬取马云的微博功能示例
2019/02/16 Python
Django实现发送邮件找回密码功能
2019/08/12 Python
django数据模型on_delete, db_constraint的使用详解
2019/12/24 Python
Python读取多列数据以及用matplotlib制作图表方法实例
2020/09/23 Python
分享unittest单元测试框架中几种常用的用例加载方法
2020/12/02 Python
CSS3 毛玻璃效果
2019/08/14 HTML / CSS
中国第一家杂志折扣订阅网:杂志铺
2016/08/30 全球购物
Peter Millar官网:美国高档生活服饰品牌
2018/07/02 全球购物
不用游标的SQL语句有哪些
2012/09/07 面试题
直接有效的自我评价
2014/01/11 职场文书
班级安全教育实施方案
2014/02/23 职场文书
百货商场楼层班组长竞聘书
2014/03/31 职场文书
机关作风整顿个人剖析材料
2014/10/06 职场文书
企业愿景口号
2015/12/25 职场文书
Python 数据可视化神器Pyecharts绘制图像练习
2022/02/28 Python