python Django框架實(shí)現(xiàn)自定義表單提交
除了使用Django內(nèi)置表單,有時(shí)往往我們需要自定義表單。對(duì)于自定義表單Post方式提交往往會(huì)帶來由CSRF(跨站請(qǐng)求偽造)產(chǎn)生的錯(cuò)誤"CSRF verification failed. Request aborted."
本篇文章主要針對(duì)"表單提交"和"Ajax提交"兩種方式來解決CSRF帶來的錯(cuò)誤
一、表單提交
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>計(jì)算數(shù)字和</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="開始計(jì)算">
</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>標(biāo)簽內(nèi)添加{% csrf_token %},這樣在表單提交的過程中,會(huì)產(chǎn)生"csrfmiddlewaretoken"標(biāo)識(shí)去防止CSRF
(2)在Get請(qǐng)求頁面時(shí),需要添加context_instance=RequestContext(request) ,它和{% csrf_token %}配合使用,缺少一個(gè)都會(huì)出現(xiàn)上述錯(cuò)誤,RequestContext 需要在 django.shortcuts 導(dǎo)入
(3)只有當(dāng)表單以Post方式提交時(shí),才需要驗(yàn)證CSRF,Get方式是不需要的
二、Ajax提交
同比與表單提交,Ajax提交需要進(jìn)行額外的操作,Ajax提交時(shí)需要自己提供"csrfmiddlewaretoken"標(biāo)識(shí)參數(shù)。我們除了需要引入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="開始計(jì)算">
<h1>計(jì)算的結(jié)果為:<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就可以自動(dòng)幫我們生成"csrfmiddlewaretoken"標(biāo)識(shí),接下來你就可以使用$.post()了
$.ajaxSetup({
data:{csrfmiddlewaretoken: '{{ csrf_token }}'}
});
(2)context_instance=RequestContext(request) 并不是必須的
(3)Get請(qǐng)求不需要以上操作,直接使用$.get()即可
注:本文使用的Django1.8.3版本進(jìn)行測(cè)試。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
相關(guān)文章
python之pygame模塊實(shí)現(xiàn)飛機(jī)大戰(zhàn)完整代碼
這篇文章主要為大家詳細(xì)介紹了python之pygame模塊實(shí)現(xiàn)飛機(jī)大戰(zhàn)完整代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
python使用paramiko執(zhí)行服務(wù)器腳本并拿到實(shí)時(shí)結(jié)果
這篇文章主要介紹了python使用paramiko執(zhí)行服務(wù)器腳本并拿到實(shí)時(shí)結(jié)果,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
pandas 如何保存數(shù)據(jù)到excel,csv
這篇文章主要介紹了pandas 如何保存數(shù)據(jù)到excel,csv的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
一文帶你了解Python列表生成式應(yīng)用的八重境界
在Python中有非常多且好用的技巧,其中使用最多的是列表生成式,往往可以將復(fù)雜的邏輯用簡(jiǎn)單的語言來實(shí)現(xiàn),本文重點(diǎn)介紹列表生成式應(yīng)用的八重境界2022-09-09
anaconda3安裝及jupyter環(huán)境配置全教程
這篇文章主要介紹了anaconda3安裝及jupyter環(huán)境配置全教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08
利用Python實(shí)現(xiàn)簡(jiǎn)單的Excel統(tǒng)計(jì)函數(shù)
這篇文章主要介紹了利用Python實(shí)現(xiàn)簡(jiǎn)單的Excel統(tǒng)計(jì)函數(shù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07
解決python執(zhí)行不輸出系統(tǒng)命令彈框的問題
今天小編就為大家分享一篇解決python執(zhí)行不輸出系統(tǒng)命令彈框的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-06-06

