三、Ajax操作
ajax操作基於瀏覽器的xmlHttpRequest對象,IE低版本是另外一個對象,jQuery 1 版本對那兩個對象做了封裝,兼容性最好,2 、3版本不再支持IE低版本了。
Ajax操作,用來偷偷發請求。
參考博客:
http://www.cnblogs.com/wupeiqi/articles/5703697.html
1、原生Ajax操作
XmlHttpRequest對象介紹
- XmlHttpRequest對象的主要方法:
void open(String method,String url,Boolen async)
用於創建請求
參數:
method: 請求方式(字符串類型),如:POST、GET、DELETE...
url: 要請求的地址(字符串類型)
async: 是否異步(布爾類型)
void send(String body)
用於發送請求
參數:
body: 要發送的數據(字符串類型)
void setRequestHeader(String header,String value)
用於設置請求頭
參數:
header: 請求頭的key(字符串類型)
vlaue: 請求頭的value(字符串類型)
String getAllResponseHeaders()
獲取所有響應頭
返回值:
響應頭數據(字符串類型)
String getResponseHeader(String header)
獲取響應頭中指定header的值
參數:
header: 響應頭的key(字符串類型)
返回值:
響應頭中指定的header對應的值
void abort()
終止請求
- XmlHttpRequest對象的主要屬性:
a. Number readyState
狀態值(整數)
詳細:
0-未初始化,尚未調用open()方法;
1-啓動,調用了open()方法,未調用send()方法;
2-發送,已經調用了send()方法,未接收到響應;
3-接收,已經接收到部分響應數據;
4-完成,已經接收到全部響應數據;
b. Function onreadystatechange
當readyState的值改變時自動觸發執行其對應的函數(回調函數)
c. String responseText
服務器返回的數據(字符串類型)
d. XmlDocument responseXML
服務器返回的數據(Xml對象)
e. Number states
狀態碼(整數),如:200、404...
f. String statesText
狀態文本(字符串),如:OK、NotFound...
原生ajax示例
ajax.html
<body>
<input type="text" />
<input type="button" value="Ajax1" onclick="Ajax1();" />
<script>
function Ajax1(){
var xhr = new XMLHttpRequest(); // 創建XMLHttpRequest對象
xhr.open('GET','/ajax_json/',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 接收完畢
var obj = JSON.parse(xhr.responseText);
console.log(obj)
}
};
xhr.setRequestHeader('k1','v1'); // 設置數據頭
xhr.send("name=root;pwd=123");
}
</script>
</body>
urls.py
url(r'^ajax_json/', views.ajax_json),
url(r'^ajax/', views.ajax),
views.py
def ajax(request):
return render(request, "ajax.html")
def ajax_json(request):
print(request.POST)
ret = {'code':True, 'data':None}
import json
# return HttpResponse(json.dumps(ret),status=404,reason='Not Found') # 定義狀態碼及狀態信息
return HttpResponse(json.dumps(ret))
上面發送的是GET請求,如果是POST請求呢?
如上如果是POST請求,views裏print(request.POST)
是沒有數據的,因爲POST請求需要給加上請求頭。
<script>
function Ajax1(){
var xhr = new XMLHttpRequest(); // 創建XMLHttpRequest對象
xhr.open('POST','/ajax_json/',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 接收完畢
var obj = JSON.parse(xhr.responseText);
console.log(obj)
}
};
xhr.setRequestHeader('k1','v1'); // 設置數據頭
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
xhr.send("name=root;pwd=123");
}
</script>
兼容性問題
以下幾種寫法,都是一樣的效果
> XMLHttpRequest
XMLHttpRequest()
> window.XMLHttpRequest
XMLHttpRequest()
> window['XMLHttpRequest']
XMLHttpRequest()
- XmlHttpRequest
IE7+, Firefox, Chrome, Opera, etc. - ActiveXObject(“Microsoft.XMLHTTP”)
IE6, IE5
<script type="text/javascript">
function getXHR(){ // 兼容性判斷
var xhr = null;
if(XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
return xhr;
}
function XhrPostRequest(){
var xhr = getXHR();
// 定義回調函數
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 已經接收到全部響應數據,執行以下操作
var data = xhr.responseText;
console.log(data);
}
};
// 指定連接方式和地址----文件方式
xhr.open('POST', "/test/", true);
// 設置請求頭
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
// 發送請求
xhr.send('n1=1;n2=2;');
}
function XhrGetRequest(){
var xhr = GetXHR();
// 定義回調函數
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 已經接收到全部響應數據,執行以下操作
var data = xhr.responseText;
console.log(data);
}
};
// 指定連接方式和地址----文件方式
xhr.open('get', "/test/", true);
// 發送請求
xhr.send();
}
</script>
jQuery的ajax
如果在jQuery的ajax的回調函數裏,再寫上一些參數,裏面的參數接收的就是xmlHttpRequest對象,功能和上面是一模一樣的。
2、僞ajax(iframe標籤)
iframe標籤,會把網址嵌套在網頁中,iframe裏的網址更改,網頁是不刷新的。
<iframe src="http://blog.csdn.net/fgf00"></iframe>
示例:輸入http://……
網址,跳轉
<body>
<input type="text" id="url" />
<input type="button" value="Iframe請求" onclick="iframeRequest();" />
<iframe src="http://blog.csdn.net/fgf00" id="ifm"></iframe>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function iframeRequest(){
var url = $('#url').val();
console.log(url);
$('#ifm').attr('src',url);
}
</script>
</body>
示例:iframe僞ajax提交
可以把form提交轉交給iframe,iframe提交,利用這個特性,實現僞ajax操作。
ajax.html
<form action="/ajax_json/" method="POST" target="ifm1">
{% csrf_token %}
<iframe id="ifm1" name="ifm1"></iframe>
<input type="text" name="username" placeholder="用戶名"/>
<input type="text" name="email" placeholder="郵箱地址"/>
<input type="submit" value="Form提交">
</form>
views.py
def ajax_json(request):
print(request.POST)
ret = {'code':True, 'data':request.POST.get('username')}
import json
return HttpResponse(json.dumps(ret))
阻止iframe裏引用的網頁自動跳轉
在一些新版本的瀏覽器裏,iframe標籤居然自動跳轉,禁用如下:
在iframe標籤中增加兩個屬性:
security="restricted" sandbox=""
前者是IE的禁止js的功能,後者是HTML5的功能。剛好就可以讓IE,Chrome,Firefox這三大瀏覽器都實現了禁止iframe的自動跳轉。
iframe獲取返回的數據
瀏覽器審查元素中,iframe加載的時候在document對象裏,相當於一個上下文或者空間管理,在HTML裏面又嵌套了一個HTML。不能通過以前的方法獲取到。
iframe接收到服務端返回的數據後,會執行onload
事件,獲取返回數據如下:
<form action="/ajax_json/" method="POST" target="ifm1">
{% csrf_token %}
<iframe id="ifm1" name="ifm1" onload="iframeLoad();"></iframe>
<input type="text" name="username" placeholder="用戶名"/>
<input type="text" name="email" placeholder="郵箱地址"/>
<input type="submit" value="Form提交" onclick="submitForm();"/>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function submitForm(){ // 當點擊提交的時候,纔給iframe綁定load事件
// 比在html中這樣添加好一點:<iframe name="ifm1" οnlοad="iframeLoad();"></iframe>
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text(); // document對象下面的值
var obj = JSON.parse(text);
console.log(obj);
})
}
function iiframeLoad(){
console.log(123)
}
</script>
ajax操作,使用方式選擇
如果發送的是【普通數據】 : jQuery > XMLHttpRequest > iframe
3、ajax 文件上傳(三種方式)及 圖片預覽
urls.py
url(r'^upload/$', views.upload),
url(r'^upload_file/', views.upload_file),
views.py
def upload(request):
return render(request,'upload.html')
def upload_file(request):
username = request.POST.get('username')
fafafa = request.FILES.get('fafafa')
import os
img_path = os.path.join('static/imgs/',fafafa.name)
with open(img_path,'wb') as f:
for item in fafafa.chunks():
f.write(item)
ret = {'code': True , 'data': img_path} # 返回文件路徑(圖片預覽用)
import json
return HttpResponse(json.dumps(ret))
upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.upload{
display: inline-block;padding: 10px;
background-color: #2459A2;
color: white;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 90;
}
.file{
width: 60px;height: 30px;opacity: 0;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
z-index: 100;
}
</style>
</head>
<body>
<div style="position: relative;width: 60px;height: 30px;">
<input class="file" type="file" id="fafafa" name="afafaf" />
<a class="upload">上傳</a>
</div>
<input type="button" value="提交XHR" onclick="xhrSubmit();" />
<input type="button" value="提交jQuery" onclick="jqSubmit();" />
<hr/>
<form id="form1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
<iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
<input type="file" name="fafafa"/>
<input type="submit" onclick="iframeSubmit();" value="iframe提交"/> <!--iframe方式提交-->
<hr>選中後,就上傳、圖片預覽 <!--iframe方式提交,選中後,就上傳,並圖片預覽-->
<input type="file" name="fafafa" onchange="changeUpalod();" /> <!--iframe方式提交,選擇後,就圖片預覽-->
</form>
<div id="preview"></div> <!-- 圖片預覽使用 -->
<script src="/static/jquery-1.12.4.js"></script>
<script>
// 選中後,就上傳文件,並圖片預覽
function changeUpalod(){
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
$('#preview').empty();
var imgTag = document.createElement('img');
imgTag.src = "/" + obj.data;
$('#preview').append(imgTag);
});
$('#form1').submit();
}
// 第二種方式:基於jQuery方式上傳文件
function jqSubmit(){
// $('#fafafa')[0]
var file_obj = document.getElementById('fafafa').files[0]; // files代表上傳的文件
var fd = new FormData(); // 相當於表單
fd.append('username','root');
fd.append('fafafa',file_obj);
$.ajax({
url: '/upload_file/',
type: 'POST',
data: fd,
// 上傳文件時,添加以下兩個參數是告訴jQuery,不要做特殊處理
processData: false, // tell jQuery not to process the data
contentType: false, // tell jQuery not to set contentType
success:function(arg,a1,a2){
console.log(arg);
console.log(a1);
console.log(a2); // 多寫幾個參數,這個參數包含xmlHttpRequest對象
}
})
}
// 第一種方式:基於xmlHttpRequest方式上傳文件
function xhrSubmit(){
// $('#fafafa')[0]
var file_obj = document.getElementById('fafafa').files[0];
var fd = new FormData();
fd.append('username','root');
fd.append('fafafa',file_obj);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload_file/',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 接收完畢
var obj = JSON.parse(xhr.responseText);
console.log(obj);
}
};
xhr.send(fd);
}
// 第三種方式:基於iframe方式上傳文件
function iframeSubmit(){
$('#ifm1').load(function(){
var text = $('#ifm1').contents().find('body').text();
var obj = JSON.parse(text);
// 圖片預覽
$('#preview').empty(); // 清空之前的預覽圖片
var imgTag = document.createElement('img');
imgTag.src = "/" + obj.data; // 綁定預覽圖片路徑
$('#preview').append(imgTag);
})
}
</script>
</body>
</html>
xmlHttpRequest和jQuery上傳文件,都是基於FormData,但是FormData對於IE一些低版本瀏覽器是不支持的。
一般情況下,上傳圖片、頭像都是用iframe來實現的。
ajax操作,使用方式選擇
如果發送的是【文件】 : iframe > jQuery(FormData) > XMLHttpRequest(FormData)
四、圖片驗證碼
流程:
- 訪問頁面
`/login/
- 創建一個圖片並給用戶返回
- Session存放驗證碼
- 用戶POST提交數據,對比
實現:
頁面生成返回和生成圖片:生成網頁html、生成圖片url分開,這樣更新驗證碼圖片是,網頁是不用刷新的。
views
from io import BytesIO
from django.shortcuts import HttpResponse
from utils.check_code import create_validate_code
def check_code(request):
"""
驗證碼
:param request:
:return:
"""
# 直接打開圖片,返回
# data = open('static/imgs/avatar/20130809170025.png','rb').read()
# return HttpResponse(data)
# 通過模塊生成圖片並返回
# 1. 創建一張圖片 pip3 install Pillow
# 2. 在圖片中寫入隨機字符串
# obj = object()
# 3. 將圖片寫入到指定文件
# 4. 打開指定目錄文件,讀取內容
# 5. HttpResponse(data)
stream = BytesIO() # 在內存裏開闢一塊空間,在內存裏直接讀寫,相當於打開一個文件
img, code = create_validate_code()
img.save(stream,'PNG') # 把生成的圖片進行保存
request.session['CheckCode'] = code # 把驗證碼放入session中
return HttpResponse(stream.getvalue()) # 在內存中讀取並返回
create_validate_code
font_type="Monaco.ttf", # 依賴的字體
html
<img src="/check_code.html" onclick="changeCheckCode(this);">
<script>
function changeCheckCode(ths){
ths.src = ths.src + '?'; // URL不變:瀏覽器不發請求;加上?號,get參數請求,向後臺發請求
}
</script>
check_code.py(依賴:Pillow,字體文件)
pip3 install Pillow
五、KindEditor富文本編輯器
常用的富文本編輯器:CKEditor,UEEditor,TinyEditor,KindEditor
文件夾說明
├── asp asp示例
├── asp.net asp.net示例
├── attached 空文件夾,放置關聯文件attached
├── examples HTML示例
├── jsp java示例
├── kindeditor-all-min.js 全部JS(壓縮)
├── kindeditor-all.js 全部JS(未壓縮)
├── kindeditor-min.js 僅KindEditor JS(壓縮)
├── kindeditor.js 僅KindEditor JS(未壓縮)
├── lang 支持語言
├── license.txt License
├── php PHP示例
├── plugins KindEditor內部使用的插件
└── themes KindEditor主題
基本使用
<textarea name="content" id="content"></textarea>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/plugins/kind-editor/kindeditor-all.js"></script>
<script>
$(function () {
initKindEditor();
});
function initKindEditor() {
var kind = KindEditor.create('#content', {
width: '100%', // 文本框寬度(可以百分比或像素)
height: '300px', // 文本框高度(只能像素)
minWidth: 200, // 最小寬度(數字)
minHeight: 400 // 最小高度(數字)
});
}
</script>
詳細參數
http://kindeditor.net/docs/option.html
常用參數
items¶ # 配置顯示多少個工具
noDisableItems¶ # designMode 爲false時,要保留的工具,置灰
filterMode¶ # true時根據 htmlTags 過濾HTML代碼,false時允許輸入任何代碼。
resizeType¶ # 2或1或0,2時可以拖動改變寬度和高度,1時只能改變高度,0時不能拖動。
syncType¶ # 設置”“、”form”,值爲form時提交form時自動提交,空時不會自動提交。
uploadJson¶ # 指定上傳文件的服務器端程序。
autoHeightMode¶ # 內容多時,自動調整高度。
- uploadjson
<textarea id="content"></textarea>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script>
<script>
KindEditor.create('#content', {
uploadJson: '/upload_img/',
fileManagerJson: '/file_manager/', // 文件管理路徑
allowImageRemote: true, // 是否允許遠程上傳
allowImageUpload: true, // 是否允許本地上傳
allowFileManager: true, // 圖片空間,文件預覽功能
extraFileUploadParams: { // CSRF限制,提交csrf
csrfmiddlewaretoken: "{{ csrf_token }}"
},
filePostName: 'fafafa' // 設置文件發送的name值,方便後臺獲取
});
})
</script>
def upload_img(request):
request.GET.get('dir')
print(request.FILES.get('fafafa'))
# 獲取文件保存
import json
dic = {
'error': 0,
'url': '/static/imgs/20130809170025.png',
'message': '錯誤了...'
}
return HttpResponse(json.dumps(dic))
import os, time, json
def file_manager(request):
"""
文件管理,照片空間
:param request:
:return:
"""
dic = {}
root_path = 'C:/Users/Administrator/PycharmProjects/day24/static/'
static_root_path = '/static/'
request_path = request.GET.get('path')
if request_path:
abs_current_dir_path = os.path.join(root_path, request_path)
move_up_dir_path = os.path.dirname(request_path.rstrip('/'))
dic['moveup_dir_path'] = move_up_dir_path + '/' if move_up_dir_path else move_up_dir_path
else:
abs_current_dir_path = root_path
dic['moveup_dir_path'] = ''
dic['current_dir_path'] = request_path
dic['current_url'] = os.path.join(static_root_path, request_path)
file_list = []
for item in os.listdir(abs_current_dir_path):
abs_item_path = os.path.join(abs_current_dir_path, item)
a, exts = os.path.splitext(item)
is_dir = os.path.isdir(abs_item_path)
if is_dir:
temp = {
'is_dir': True,
'has_file': True,
'filesize': 0,
'dir_path': '',
'is_photo': False,
'filetype': '',
'filename': item,
'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
}
else:
temp = {
'is_dir': False,
'has_file': False,
'filesize': os.stat(abs_item_path).st_size,
'dir_path': '',
'is_photo': True if exts.lower() in ['.jpg', '.png', '.jpeg'] else False,
'filetype': exts.lower().strip('.'),
'filename': item,
'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
}
file_list.append(temp)
dic['file_list'] = file_list
return HttpResponse(json.dumps(dic))
轉載請務必保留此出處:http://blog.csdn.net/fgf00/article/details/54917439