django实现文件上传
使用form表单上传文件
- html页面
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.img {
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<form id="myform" method="POST" action="/upload/" enctype="multipart/form-data">
<input type="text" name="byd" id="byd" placeholder="请输入字符串"> <input type="file" name="img" id="img" value="手动点击上传图片">
<input type="submit" name="提交">
</form>
</body>
</html>
- django view配置
import os
import time
import json stat = {'status':False,'data':None,'msg':None}
def upload(request):
if request.method == 'POST':
try:
user = request.POST.get('byd')
img = request.FILES.get('img')
img_path = os.path.join('static',img.name)
f = open(img_path,'wb')
for chunk in img.chunks():
f.write(chunk)
f.close()
stat['status'] = True
stat['data'] = img_path
except Exception as e:
stat['msg'] = str(e)
finally:
return HttpResponse(json.dumps(stat))
else:
return render(request,'upload.html')
涉及的知识:
- 1) 表单上传的文件对象存储在类字典对象request.FILES中,表单格式需为multipart/form-data
- 2)request.FILES中的键来自于表单中的
<input type="file" name="" />
的name值:- 3)request.FILES中的值均为UploadedFile类文件对象。
UploadedFile
UploadedFile是类文件对象,具有以下方法和属性: UploadedFile.read() 读取整个上传文件的数据,文件较大时慎用。 UploadedFile.multiple_chunks(chunk_size=None) 判断文件是否足够大,一般为2.5M UploadedFile.chunks(chunk_size=None) 返回一个生成器对象,当multiple_chunks()为True时应该使用这个方法来代替read(). UploadedFile.name 上传文件的name。 UploadedFile.size 上传文件的大小。 UploadedFile.content_type 上传文件时的content_type报头,例如(e.g. text/plain or application/pdf). UpladedFile.charset 编码
- 4) 存储上传的数据。注意上传的是二进制文件,所以需使用wb模式打开文件
f = open(img_path,'wb')
for chunk in img.chunks():
f.write(chunk)
f.close()
使用django自带的Form处理上传文件
form表单
from django import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
view函数
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from somewhere import handle_uploader_file
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/success/url')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})
使用html的form表单上传,当提交文件之后,本页面会刷新,如果要实现上传文件页面不刷新,需要使用强大的ajax
使用ajax上传文件
我们平时使用jquery的ajax方法做post上传,其实是调用了ajax原生的XMLHttpRequest来发送请求。原生的ajax 上传文件涉及到两个对象FormData和XMLHttpRequest,具体参数请点击这里:http://www.cnblogs.com/pycode/p/django02.html
原生ajax http请求
- html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
{{ crruent_time }}
<input type="button" value="XMLHttpRequest按钮" onclick="XhrAjax();"/>
<input type="button" value="XMLHttpRequest,FormData按钮" onclick="XhrAjaxForm();"/>
<script>
function XhrAjax(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
// 只有服务器端返回数据时,处理请求
if(xhr.readyState == 4){
// 服务器端响应的内容已经接受完毕
console.log(xhr.responseText);
}
};
// GET请求
//xhr.open('GET', '/xhr_ajax?p=123');
//xhr.send();
// POST请求
xhr.open('POST', '/xhr_ajax/');
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
xhr.send("k1=v1;k2=v2");
}
function XhrAjaxForm(){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
// 只有服务器端返回数据时,处理请求
if(xhr.readyState == 4){
// 服务器端响应的内容已经接受完毕
console.log(xhr.responseText);
}
};
// GET请求
//xhr.open('GET', '/xhr_ajax?p=123');
//xhr.send();
// POST请求
xhr.open('POST', '/xhr_ajax/');
// 设置请求头
// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
var form = new FormData();
form.append('user', 'alex');
form.append('pwd', '');
xhr.send(form);
}
</script>
</body>
</html>
- view视图
def ajax(request):
current_time = time.time()
return render(request,'ajax.html',{'current_time':current_time})
def xhr_ajax(request):
print(request.POST)
print(request.GET)
return HttpResponse('ok')
原生ajax的XmlHttpRequest相关方法:
a. void open(String method,String url,Boolen async)
用于创建请求 参数:
method: 请求方式(字符串类型),如:POST、GET、DELETE...
url: 要请求的地址(字符串类型)
async: 是否异步(布尔类型) b. void send(String body)
用于发送请求 参数:
body: 要发送的数据(字符串类型) c. void setRequestHeader(String header,String value)
用于设置请求头 参数:
header: 请求头的key(字符串类型)
vlaue: 请求头的value(字符串类型) d. String getAllResponseHeaders()
获取所有响应头 返回值:
响应头数据(字符串类型) e. String getResponseHeader(String header)
获取响应头中指定header的值 参数:
header: 响应头的key(字符串类型) 返回值:
响应头中指定的header对应的值 f. void abort() 终止请求
原生ajax的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 上传文件
- html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="myform">
<input type="text" name="byd" id="byd" placeholder="请输入字符串">
<input type="file" name="img" id="img" value="手动点击上传图片">
</form>
<a href="javascript:void(0)" style="margin:20px 0 0 20px;background-color: #2aabd2;color: white;display: inline-block;" onclick="ajax_upload();">Ajax原生上传</a>
</body>
</html>
- js
function ajax_upload() {
var form = new FormData();
var xhr = new XMLHttpRequest();
var fileobj = document.getElementById('img').files[0];
form.append('byd',document.getElementById('byd').value);
form.append('img',fileobj);
xhr.onreadystatechange = function(){
// 只有服务器端返回数据时,处理请求
if(xhr.readyState == 4){
// 服务器端响应的内容已经接受完毕
console.log(xhr.responseText);
}
};
xhr.open('POST', '/upload/');
xhr.send(form); }
- view实图 同html form
使用jquery上传文件
- html文件
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="myform">
<input type="text" name="byd" id="byd" placeholder="请输入字符串">
<input type="file" name="img" id="img" value="手动点击上传图片">
</form>
<a href="javascript:void(0)" style="margin:20px 0 0 20px;background-color: #2aabd2;color: white;display: inline-block;" onclick="jquery_upload();">jquery上传</a>
</body>
</html>
- js文件
function jquery_upload() {
//jquery和dom对象互相转换
//jquery --> dom jqueryobj[0]
// dom--->jquery $(domobj)
var fileobj = $('#img')[0].files[0]; //先将jquery对象转换为dom对象
var form = new FormData();
form.append('byd',$('#byd').val());
form.append('img',fileobj);
$.ajax({
url:'/upload/',
type:'POST',
data:form,
processData:false, //设置不对数据进行自处理,默认jquery会对上传的数据进行处理
contentType:false, //设置不添加请求头的内容类型
success:function (arg) {
alert(arg)
} })
}
- view实图 同html form
利用iframe使用伪ajax请求
不论是jquey或原生ajax,对以前的浏览器版本(ie6)以前是不兼容的,所以,如果要兼容以前的浏览器,可以使用iframe伪造ajax请求来进行文件上传
- html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.img {
width: 300px;
height: 300px;
}
</style>
</head>
<body>
<iframe name="myiframe" id="myiframe" style="display: none;"></iframe>
<form id="myform" method="POST" action="/upload/" enctype="multipart/form-data" target="myiframe">
<input type="text" name="byd" id="byd" placeholder="请输入字符串">
<input type="file" name="img" id="img" value="手动点击上传图片">
<input type="file" name="img" id="img2" value="自动上传图片" onchange="iframe_upload()">
<input type="submit" name="提交">
</form>
<a href="javascript:void(0)" style="margin:20px 0 0 20px;background-color:peru;color: white;display: inline-block;" onclick="iframe_upload();">Iframe上传</a> </body>
</html>
- js
function iframe_upload() {
$('#content_img').find('img').remove();
document.getElementById('myiframe').onload = callback;
document.getElementById('myform').target = "myiframe";
document.getElementById('myform').submit(); }
function callback() {
var text = $('#myiframe').contents().find('body').text();
var resault = JSON.parse(text);
if (resault.status) {
var tag = document.createElement('img');
tag.className = 'img';
tag.src = "/" + resault.data;
$('#content_img').append(tag);
} else {
alert(resault.msg)
} }
注意:
1、需要设置iframe的name值与form的target属性值一样,意思就是把form表单上传文件的刷新转嫁到iframe里去了;
2、form表单的enctype属性值必须设置成multipart/form-data,将文件转换成文件流供后端接收;
django models对象queryset序列化
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
- serializers
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json", ret)
- json.dumps
import json #ret = models.BookType.objects.all().values('caption')
ret = models.BookType.objects.all().values_list('caption') ret=list(ret) result = json.dumps(ret)
由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:
import json
from datetime import date
from datetime import datetime class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field, date):
return field.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, field) ds = json.dumps(d, cls=JsonCustomEncoder)