注:本人使用的Django1.8.3版本进行测试

除了使用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()即可

总结:本人学习Django的时间不长,写博客的目的只要是为了自己做知识记录和对知识的分享,如果哪里写的不好,还请广大博友指点,多多包涵。

Django初体验(一):自定义表单提交的更多相关文章

  1. phpcms v9自定义表单提交后返回上一页实现方法

    PHPcms v9中提交自定义表单后默认都是回到首页的,是不是感觉很不爽! 接下来,就说下phpcms v9自定义表单提交后返回上一页实现方法. 1.找到这个文件 phpcms\modules\for ...

  2. DedeCMS实现自定义表单提交后发送指定QQ邮箱法

    https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=monline_3_dg&wd=dedecms 邮箱&oq=d ...

  3. dedecms自定义表单提交成功后提示信息修改和跳转链接修改

    我们在用dedecms自定义表单提交成功后提示信息一般是"Dedecms 提示信息",这个要怎么改成自己想要的文字呢?还有就是提示页停留时间,目前估计就2秒,太快了,要如何设置长点 ...

  4. DedeCMS实现自定义表单提交后发送指定QQ邮箱的方法

    如月cruyue在做DedeCMS自定义表单发送邮箱的教程,发现大部分都是在php文件里写死固定字段内容,这样虽然也能实现自定义表单提交后发送指定邮箱,但是很不智能,如月cruyue想要一个我们自定义 ...

  5. [转]django自定义表单提交

    原文网址:http://www.cnblogs.com/retop/p/4677148.html 注:本人使用的Django1.8.3版本进行测试 除了使用Django内置表单,有时往往我们需要自定义 ...

  6. DEDECMS自定义表单提交后的跳转链接修改方法

    dedecms自定义表单,点击提交后,默认跳转到首页,我们打开plus/diy.php,里面有这样一段代码: 代码如下:if($dsql->executenonequery($query)) { ...

  7. 织梦DedeCMS自定义表单提交成功后返回当前页面的教程

    织梦的自定义表单制作的留言,报名等功能,提交成功后会自动返回到首页,那么如何让它返回到当前页面呢? 方法如下: 打开plus/diy.php文件 找到 showmsg($bkmsg, $goto); ...

  8. dedecms自定义表单提交获取时间跟ip地址

    相信大家在用织梦做网站的时候都用过自定义表单做留言,但是如何查看客户什么时间填写的表单,和客户的IP地址呢? 我在网上找了很多JS文件,但太繁琐了,后来我注意到一个细节,每次我登陆后台,织梦系统都会记 ...

  9. JS自定义表单提交处理方案

    JS自定义数据提交处理方案 问题 在Ajax技术流行的今天,我遇到了一个很头疼的问题,我需要维护一个前人开发的问题单模块功能,并且不停的迭代开发,而这个问题就是问题单字段特别多,而且除了更新问题单外, ...

随机推荐

  1. Django 模版语言详解

    一.简介 模版是纯文本文件.它可以产生任何基于文本的的格式(HTML,XML,CSV等等). 模版包括在使用时会被值替换掉的 变量,和控制模版逻辑的 标签. 例: {% extends "b ...

  2. Wowza® Media Systems 使用配置手册。

    准备 1,先安装Java:http://www.java.com/zh_CN/ 2,官网下载安装:http://www.wowza.com/pricing/installer ,需要输入用户名邮箱等信 ...

  3. 请使用java来构造和遍历二叉树?

    [分析] 二叉树的结构:根节点.左子树.右子树.其中左子树的值必须小于根节点,右子树的值必须大于根节点.构造这种树结构,就是创建一个类,并提供一个方法,当给定一个值时,它能够自动创建节点并自动挂到二叉 ...

  4. sizzle源码分析 (1)sizzle架构

    sizzle是jquery的核心,它用来选择匹配的元素,其代码包含在一个匿名函数中,并以window作为其上下文环境: (function( window, undefined ) { //此处为si ...

  5. 从零开始,做一个NodeJS博客(零):整体规(chui)划(niu)

    标签:NodeJS,Heroku 0 搭建一个个人独立博客,这是我好久之前就在计划的一件事了. 这个暑假,我学习了廖雪峰老师的NodeJS教程,又偶然在V2EX上发现了Heroku这个平台,可以免费在 ...

  6. Javascript到PHP加密通讯的简单实现

    其实内容主要来源于上一篇博文,只是重新组织了语言,并做了原理性的阐述,更容易理解:P ----------------------------------------- 华丽的分割线 -------- ...

  7. SharePoint 2013 初始化Ribbon选中Tab

    SharePoint使用中,经常打开页面会有默认展开的Ribbon选项,有时这又不是我们需要的,所以我们就需要默认选中的项目,下面简单介绍下如何实现. 方法一 1.Dispform.aspx页面默认R ...

  8. SQLite Design and Concepts

    API 分为两大类 core API. 基本的SQL操作 extension API. 创建自定义的SQL操作. 基本数据结构 需要了解的组成部分有连接.statments.B树.pager. 为了写 ...

  9. Android studio 克隆分支

    1.当远程仓库有两个分支时,像这样的 获得分支的远程仓库地址 注意:这个地址默认就是克隆master 分支 2.如何克隆 v1.2 分支 ? 用android studio 把项目打开,可以看到 此时 ...

  10. 数据结构--用Objective-C简单实现的数据结构:栈

    前言:最近在学习数据结构,这里用Objective-C简单实现了一下栈.用Objective-C确实好容易,因为我使用了Cocoa框架提供了NSMutableArray作为存储元素的集合,操作集合元素 ...