向后台传输数据有两种方式1、form 提交后会刷新页面 2、ajax 提交数据后不会刷新页面
ajax是XMLHttPRequest对象。使用ajax分为3种情况,1、手动使用 2、jQuery方式使用 3、伪ajax
1、当遇到需求,不使用jQuery方式用ajax向后台发送数据。
<a href="#" onclick="func()">点击</a>
???function func() { ???????var xhr = new XMLHttpRequest();//创建XMLHttpRequest对象 ???????xhr.onreadystatechange = function(){ ???????????if(xhr.readyState == 4){ ???????????????console.log(xhr.responseText);//xhr.responseText保存着服务端返回来的信息 ???????????} ???????};//以XMLHttpRequest对象向后台发送数据执行的回调函数,某些状态更改会触发执行。 ???????//xhr.readyState取值有0-4 ???????xhr.open("GET", "/ajax_2?p=123"); ???????xhr.send(null); ???}
def ajax_2(request): ???print(request.POST) ???print(request.GET) ???return HttpResponse("ok")
后台没有对接收到的数据进行处理,只是打印接收到的数据。
上述代码的步骤为:1、创建 XMLHttpRequest对象,2、根据该对象设置回调函数,3、以什么方式,向哪个url创建连接,4、发送数据。回调函数中,xhr的状态改变就会触发回调函数的执行,其状态保存在xhr.readyState中,其详细的状态有
0——未初始化,尚未调用open方法
1——启动,调用了open()方法,还未调用send()方法。
2——发送,已经调用了send()方法,还未接收到响应。
3——接收,已经接收到部分响应数据。
4——完成,已经接收到全部响应数据。
发送get请求和post请求不一样,发送post请求需要设置发送的请求头。
request请求有请求头和请求体。数据发送是在request.body中,然后提取到request.GET;request.POST中,采用该方式发送数据时,请求头没有设置成Django能够识别的形式,因此需要将请求头设置成django能够识别的形式。
<a href="#" onclick="func_1()">点击</a>
???function func_1() { ???????var xhr = new XMLHttpRequest(); ???????xhr.onreadystatechange = function(){ ???????????if(xhr.readyState == 4){ ???????????????console.log(xhr.responseText); ???????????} ???????}; ???????xhr.open("POST", "/ajax_2/"); ???????xhr.setRequestHeader(‘Content-Type‘, ‘application/x-www-form-urlencoded; charset-UTF-8‘)//设置请求头,Django中固定这种设置,还可以进行其他//的设置,这样设置Django能够解析 ???????xhr.send("p=456"); ???}
def ajax_2(request): ???print(request.POST) ???print(request.GET) ???return HttpResponse("ok")
2、伪ajax
方法:采用iframe标签和form表单一起合用完成向后台发送数据而又不刷新页面。
该方法是兼容性最好的一种方式。
认识iframe:iframe有默认高度和宽度,在页面上显示类似于文本框textarea,有src属性,通过src属性发送请求,请求发送到后台,后台处理后将处理结果返回显示到iframe自己的内容区域中,外面的大的页面不刷新。
因此配合使用时需要做两点:2、在form表单上加上target="iframe标签的那么属性值"1、在iframe标签上加上name="名字"
???<iframe name="ifra_a" onload="loadData(this)" id="ifra_2"></iframe> ???<form id="fm_a" action="/file_upload_1/" method="post" enctype="multipart/form-data" target="ifra_a"> ???????<input type="file" name="test_file3" id="input_c" onchange="func_4()"> ???</form>
这样配合起来使用后,form提交到自己设定的路径的后台处理,后台处理后将处理的结果返回到iframe标签的内容区中。onchange表示输入框内容改变执行对应的函数。
回调函数,怎么取iframe标签中的值?
认识js中的this
1、在一个具体的标签中,this带指这一个标签。
在一个标签中有两种情况:1
<iframe name="ifra_a" onload="loadData(this)" id="ifra_2"></iframe>
2:
???$("#ifra_2").click(function () { ???????$(this).html(); ???})
2、没有在一个具体的标签中,this带指window对象。
func_4()实现提交form表单,相当于input标签type = ‘submit‘的情况。
???function func_4() { ???????document.getElementById("fm_a").submit() ???}
上述实现了将输入的文件提交到后台,通过视图函数处理请求。
def fileUpload1(request): ???testFile = request.FILES.get("test_file3") ???file_path = os.path.join("static",testFile.name) ???data = {"status":"ok","index":file_path} ???f = open(file_path,"wb") ???for line in testFile.chunks(): ???????f.write(line) ???f.close() ???return HttpResponse(json.dumps(data))
回调函数:图片预览
function loadData(ths) {//当iframe中数据加载后执行onload对应的函数
var data = ths.contentWindow.document.body.innerHTML; //取得body中的字符串
var data_par = JSON.parse(data);//解析json字符串
var ele = document.createElement("img");
ele.src = "/"+data_par.index; //解析后的字典中的索引赋值给img对象的src属性
$("#preview").append(ele);
}
ajax的三种方式实现文件的上传
认识FormData()对象,可以看做一个特殊的字典,在其里面可以封装数据,包括文件,消息,相对于采用字典传输数据的方式,他的优势在于能够传输文件,而字典不行。
1、jQuery
???????<input type="file" name="test_file1" id="input_a"> ???????<a onclick="submitajax()" href="#">上传</a>
???function submitajax() { ???????var testdata = new FormData(); ???????testdata.append("k",document.getElementById("input_a").files[0]); ???????$.ajax({ ???????????url:"/file_upload/", ???????????type:"POST", ???????????data:testdata, ???????????success:function (arg) { ???????????}, ???????????processData:false,//需要加上这两个参数,表示不对数据进行处理,就是不让jquery对数据处理 ???????????contentType:false, ???????}) ???}
2、原生XMLHttpR
<input type="file" id="input_file_c" onchange="submitajax_3()">
???function submitajax_3() { ???????var data = new FormData(); ???????data.append("k",document.getElementById("input_file_c").files[0]); ???????var xhr = new XMLHttpRequest(); ???????xhr.onreadystatechange = function () { ???????};//回调函数 ???????xhr.open("POST","/file_upload_3/"); ???????//xhr.setRequestHeader(‘Content-Type‘, ‘application/x-www-form-urlencoded; charset-UTF-8‘); ???????xhr.send(data) ???}
采用FormData对象提交数据和采用字典方式提交还有一点不同,不需要想后台提交请求头,字典方式组织的数据需要,不然request.POST上没有数据。jquery提交会自动处理数据会加上请求头,因此需要设置processData:false,
def fileUpload_3(request): ???print(request.POST) ???print(request.GET) ???print(request.FILES) ???testFile = request.FILES.get("k") ???file_path = os.path.join("static",testFile.name) ???data = {"status":"ok","index":file_path} ???# print(testFile.name) ???print(testFile.size) ???f = open(file_path,"wb") ???for line in testFile.chunks(): ???????f.write(line) ???f.close() ???return HttpResponse(json.dumps(data))
3、iframe和from
???????????????????<iframe style="display: none;" id="upload_iframe" name="upload_iframe"></iframe> ???????????????????<form method="POST" action="/{{ username }}/upload-avatar/" enctype="multipart/form-data" ?????????????????????????target="upload_iframe"id="upload_fm"> ???????????????????????{% csrf_token %} ???????????????????????<img id="previewImg" src="/{{ user_obj.img }}" ????????????????????????????style="border-radius: 50%;height: 70px;width: 70px"/> ???????????????????????<div class="text">点击图片更换(<a href="#">撤销</a>)</div> ???????????????????????<input id="avatarImg" name="avatar_img" type="file" class="img-file"onchange="submit_img()"/> ???????????????????</form>
???????function submit_img() { ???????????document.getElementById("upload_fm").submit(); ???????}
Jsonp和跨域访问
浏览器都有同源策略;同源策略是浏览器最核心最基本的安全功能。同源是指,域名、协议、端口相同。
同源策略分为两种:
1、DOM同源策略
2、XMLHTTPRequest同源策略
不允许使用XHR对象向不同源的服务器地址发起HTTP请求
同源策略是为了浏览器上网的安全,但是由于有了同于策略,引起了跨域访问的问题。
JSONP跨域原理:
script标签不会受到同源策略的影响,动态创建script标签,利用src跨域。
???<div id="div_jsonp_content"></div> ???<div href="" class="btn" onclick="func_jsonp()">点击</div>
???function func_jsonp() { ???????var ele = document.createElement("script"); ???????ele.src = "http://127.0.0.1:8000/jsonp-test/";//跨域访问,执行路径为下面一处贴的代码 ???????document.head.appendChild(ele);
document.head.removeChild(ele); ???} ???function f_jsonp(arg) { ???????$("#div_jsonp_content").html(arg); ???}
上述第一个函数1、先创建script标签,2、利用src跨域访问3、在head中添加标签4、移除标签
上述第二个函数,函数名和返回的字符串外层包裹相同,arg为内层字符串。
path(‘jsonp-test/‘, views.jsonp_test),//url需要跨域的服务器def jsonp_test(request): ???return HttpResponse("f_jsonp(‘jsonp_test‘)")
ajax有跨域访问的自动处理方式:对应的服务器返回同上。
<div href="" class="btn" onclick="func_jsonp1()">点击</div>
???function func_jsonp1() { ???????$.ajax({ ???????????url:"http://127.0.0.1:8000/jsonp-test/", ???????????type:"POST", ???????????dataType:‘JSONP‘, ???????}) ???}
???function f_jsonp(arg) { ???????{#$("#div_jsonp_content").html(arg);#} ???????console.log(arg) ???}
ajax跨域指定返回的回调函数:
<div href="" class="btn" onclick="func_jsonp1()">点击</div>
???function func_jsonp1() { ???????$.ajax({ ???????????url:"http://127.0.0.1:8000/jsonp-test/", ???????????type:"GET", ???????????dataType:‘JSONP‘, ???????????jsonp:"callback", ???????????jsonpCallback:"ffff", ???????}) ???}
???function ffff(arg) { ???????{#$("#div_jsonp_content").html(arg);#} ???????console.log(arg) ???}
服务器部分与先前有一些不同的地方
不同之处在视图处理函数,如下:
def jsonp_test(request): ???name = request.GET.get("callback") ???return HttpResponse("%s(‘jsonp_test‘)"%name)
ajax
原文地址:https://www.cnblogs.com/zjsthunder/p/9754486.html