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中的len()函数的使用
Apr 07 Python
Python yield 使用方法浅析
May 20 Python
利用python获取当前日期前后N天或N月日期的方法示例
Jul 30 Python
python使用KNN算法手写体识别
Feb 01 Python
windows下安装python的C扩展编译环境(解决Unable to find vcvarsall.bat)
Feb 21 Python
pandas.DataFrame 根据条件新建列并赋值的方法
Apr 08 Python
Python 中的range(),以及列表切片方法
Jul 02 Python
Python3多目标赋值及共享引用注意事项
May 27 Python
Selenium 滚动页面至元素可见的方法
Mar 18 Python
Django ForeignKey与数据库的FOREIGN KEY约束详解
May 20 Python
解决Ubuntu18中的pycharm不能调用tensorflow-gpu的问题
Sep 17 Python
python实现二分查找算法
Sep 18 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
main.php
2006/12/09 PHP
fleaphp下不确定的多条件查询的巧妙解决方法
2008/09/11 PHP
PHP可变变量学习小结
2015/11/29 PHP
twig模板常用语句实例小结
2016/02/04 PHP
浅谈PHP拦截器之__set()与__get()的理解与使用方法
2016/10/18 PHP
php cookie 详解使用实例
2016/11/03 PHP
php基于ob_start(ob_gzhandler)实现网页压缩功能的方法
2017/02/18 PHP
二级域名或跨域共享Cookies的实现方法
2008/08/07 Javascript
页面中js执行顺序
2009/11/09 Javascript
默认让页面的第一个控件选中的javascript代码
2009/12/26 Javascript
JavaScript图片轮播代码分享
2015/07/31 Javascript
AngularJs 弹出模态框(model)
2016/04/07 Javascript
表单input项使用label同时引用Bootstrap库导致input点击效果区增大问题
2016/10/11 Javascript
javascript 定时器工作原理分析
2016/12/03 Javascript
Angularjs 动态添加指令并绑定事件的方法
2017/04/13 Javascript
详解Vue基于 Nuxt.js 实现服务端渲染(SSR)
2018/04/05 Javascript
JavaScript实现电灯开关小案例
2020/03/30 Javascript
返回上一个url并刷新界面的js代码
2020/09/12 Javascript
python实现随机密码字典生成器示例
2014/04/09 Python
python中from module import * 的一个坑
2014/07/20 Python
Python创建模块及模块导入的方法
2015/05/27 Python
PyQt5每天必学之工具提示功能
2018/04/19 Python
Django静态文件加载失败解决方案
2020/08/26 Python
Pycharm Plugins加载失败问题解决方案
2020/11/28 Python
如何用Python进行时间序列分解和预测
2021/03/01 Python
css3个性化字体_动力节点Java学院整理
2017/07/12 HTML / CSS
巴西宠物商店:Cobasi
2019/04/19 全球购物
英国标志性生活方式品牌:Skinnydip London
2019/12/15 全球购物
财务管理专业自荐信范文
2013/12/24 职场文书
《猴子种树》教学反思
2014/02/14 职场文书
公司成本主管岗位责任制
2014/02/21 职场文书
目标责任书范文
2014/04/14 职场文书
新教师岗前培训方案
2014/06/05 职场文书
先进典型事迹材料
2014/12/29 职场文书
计算机教师工作总结
2015/08/13 职场文书
教你怎么用Python操作MySql数据库
2021/05/31 Python