- 请求头ContentType
ContentType指的是请求体的编码类型,常见的类型共有3种:
application/x-www-form-urlencoded
最常见的 POST 提交数据的方式了
浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 默认格式application/x-www-form-urlencoded 方式提交数据,ajax默认也是这个
urlencoded是一种数据格式,
比如:
username=yang&password=123&csrfmiddlewaretoken=.......
# 这样的一种格式,类似get请求提交数据的格式# 这样在后台,就可以通过request.POST,就可以直接拿到数据了 <QueryDict:{'username':['yang']},'password':['123'],......>
- multipart/form-data
专门用来传输文件的消息格式,会把文件作为片段数据发送,而不是整个文件一起发送 application/json
告诉服务端消息主体是序列化后的 JSON 字符串
之前给ajax传递数据,就是把字典写成了一个类似json类型的数据
def login(request):
...
ret = '{"code":0,"redirect_url":"/index/"}'
return HttpResponse(ret)在不加content_type='application/json'时,传递过去的就是一个字符串
def login(request):
d1 = {"code":0,"redirect_url":"/index/"}
import json
d1_json = json.dumps(d1)
return HttpResponse(d1_json,)success:function (res) { console.log(res,typeof res); # {"code": 0, "redirect_url": "/index/"} string .... } 这个时候,就不方便我们后续的使用,我们期望还是能拿到一个字典(自定义对象的类型)
使用content_type='application/json',ajax就会调用自己内部的反序列化机制,直接调用反序列化方法
def login(request):
d1 = {"code":0,"redirect_url":"/index/"}
import json
d1_json = json.dumps(d1)
return HttpResponse(d1_json,content_type='application/json')success:function (res) { console.log(res,typeof res); # {code: 0, redirect_url: "/index/"} "object" .... } 此时,ajax端不需要自己序列化,也拿到了object类型的对象,这是因为内部自动调用的
application/json 在ajax端发送数据,我们如何在视图函数中应用
$.ajax({
url:'{% url "data" %}',
type:'post',
data:JSON.stringify({k1:'v1',k2:'v2'}), # 序列化成字符串
contentType:'application/json', # 指定类型
....
})3 此时再 def data(request): print(request.POST) # <QueryDict: {}>,拿不到数据 print(request.body) # b'{"k1":"v1","k2":"v2"}',要从原始的数据拿 return HttpResponse('ok') b'{"k1":"v1","k2":"v2"}'
- 总之:
JsonResponse
JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应
此时传递数据的时候,既不需要自己做序列化,也不需要指定content_type='application/json',只需要把数据直接放在JsonResponse里,就会自动帮你转换成json字符串,并且自动拼接content_type='application/json',
from django.http import JsonResponse # 需要先导入
def login(request):
d1 = {"code":0,"redirect_url":"/index/"}
return JsonResponse(d1)
# 注意:字典类型可以直接JsonResponse(d1),若不是字典,是列表等,就要JsonResponse(d1,safe=False)
success:function (res) {
console.log(res,typeof res);
# {code: 0, redirect_url: "/index/"} "object"
....
}
此时,也仍然拿到了object类型的数据
例子:
需求:用户输入127.0.0.1:8000/home,通过路径返回home.html文件,home.html文件中用ajax从data路径得到数据,然后在自己页面显示成一个列表显示出来
# 配置路径:
url(r'^home/', views.home,name='home'),
url(r'^data/', views.data,name='data'),
# 视图views:
def home(request):
return render(request,'home.html')
def data(request):
# l1 = ['故人西辞黄鹤楼','烟花三月下扬州','孤帆远影碧空尽','唯见长江天际流']
l1 = [11,22,33,44]
return JsonResponse(l1,safe=False) # 列表要加safe
# home.html:
<ul></ul>
<script src="{% static 'jquery.js' %}"></script>
<script>
$.ajax({
url:'{% url "data" %}', # 从data路径获得数据
type:'get',
success:function (res) {
console.log(res);
$.each(res,function (k,v) {
# each 就是循环,k,v就是索引和值
var listr = '<li>'+ v.toString() + '</li>';
# v.toString()是把数字类型转换成字符串类型
$('ul').append(listr)
})
}
})
</script>
可见,ajax通过异步请求,在data路径拿到了数据组成了li标签,然后放在了ul标签下。
自动拼接content_type='application/json',可以从网页的Network下的XHR观察出来,XHR下的请求就是ajax请求
- 配置路径 url(r'^upload/', views.upload,name='upload'),
写视图函数
def upload(request):
if request.method == 'GET':
return render(request,'upload.html')
else:
print(request.POST)
# 拿到的是post请求的数据,文件相关数据去request.FILES拿
return HttpResponse('ok')打印的request.POST,数据如下: <QueryDict: {'csrfmiddlewaretoken': ['XR5FUZ8nf9KPo8uNzt8OD9q0OKmeVfuLEDVDyDlTMCrWtX0jvZ6gZcwwopucWQo8'], 'head_pic': ['111.png'], 'username': ['yangzm']}>
文件的数据,都在request.FILES中
# 在form表单里,要先指定消息格式
# 默认的请求消息格式是urlencoded,携带不了文件数据
# 要指定multipart/form-data才可以携带数据
def upload(request): if request.method == 'GET': return render(request,'upload.html') else: print(request.FILES) return HttpResponse('ok') # 如果form表单没有指定文件的消息格式,接收不到数据,就得到一个空字典: <MultiValueDict: {}> # 此时再打印request.FILES就拿到了上传了文件的数据: <MultiValueDict: {'head_pic': [<InMemoryUploadedFile: 111.png (image/png)>]}>
把得到的文件数据读取出来,并保存到本地
def upload(request):
if request.method == 'GET':
return render(request,'upload.html')
else:
file_obj = request.FILES.get('head_pic')
file_name = file_obj.namewith open(file_name,'wb') as f: for i in file_obj: f.write(i) return HttpResponse('ok')
以上方法上传的文件没有指定路径,就直接保存在了项目的文件夹里;此时想要把上传的文件保存在指定的文件夹中,比如项目下的statics中的img文件夹中
from ajax_pro import settings
import osdef upload(request): if request.method == 'GET': return render(request,'upload.html') else: file_obj = request.FILES.get('head_pic') file_name = file_obj.name path = os.path.join(settings.BASE_DIR,'statics','img',file_name) # 拼接路径 with open(path,'wb') as f: for i in file_obj: f.write(i) # 每次读的文件不是固定长度,每次读一行,识别符为\r,\n,,\r\n,遇到这几个符号就算是读了一行 return HttpResponse('ok')
另一种保存文件的方法:
from ajax_pro import settings
import osdef upload(request): if request.method == 'GET': return render(request,'upload.html') else: file_obj = request.FILES.get('head_pic') file_name = file_obj.name path = os.path.join(settings.BASE_DIR,'statics','img',file_name) # 拼接路径 with open(path,'wb') as f: for chunck in file_obj.chunks(): f.write(chunck) # 固定长度读取,默认一次读65536B,也就是64KB,2.5M,是一个生成器 return HttpResponse('ok')
如何获取当前文件对象的数据:$('#file')[0].files[0]
前端的html文件,用到ajax
ajax上传头像:<input type="file" id="file">
ajax用户名:<input type="text" id="uname">
<button id="btn">提交</button>
{% csrf_token %}
<script src="{% static 'jquery.js' %}"></script>
<script>
$('#btn').click(function () {
$.ajax({
url:'/upload/',
type:'post',
data:{
aa: $('#uname').val(),
head_pic:$('#file')[0].files[0],
csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val()
},
success:function (res) {
console.log(res)
}
})
})
</script>
根据以前写ajax代码的习惯,会这样写,但是会报错,因为文件上传要依靠FormData这个工具
正确写法:
ajax上传头像:<input type="file" id="file">
ajax用户名:<input type="text" id="uname">
<button id="btn">提交</button>
{% csrf_token %}
<script src="{% static 'jquery.js' %}"></script>
<script>
$('#btn').click(function () {
var formdata = new FormData();
formdata.append('aa',$('#uname').val());
formdata.append('head_pic',$('#file')[0].files[0]);
formdata.append('csrfmiddlewaretoken',$('[name=csrfmiddlewaretoken]').val());
$.ajax({
url:'/upload/',
type:'post',
data:formdata,
processData:false, //不处理数据
contentType:false, //不设置内容类型
success:function (res) {
console.log(res)
}
})
})
</script>
注意点:
- JSON 机制
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
json和python数据类型对比:
但是,json在转换时间类型的时候,会出现问题:
import datetime
import json
d = {'name':'yang','birthday':datetime.datetime.Now()}
json_str = json.dumps(d)
print(json_str)
# 报错,TypeError: Object of type 'datetime' is not JSON serializable,意思是'datetime'类型的是不能序列化的
json序列化时间日期类型的数据的方法
from datetime import date,datetime
import json
#对含有日期格式数据的json数据进行转换
class JsonCustomEncoder(json.JSONEncoder):
# 序列化的功能就是json.JSONEncoder这个类做的,因为它不能序列化时间,所以继承他的情况下进行拓展
def default(self, field):
if isinstance(field,datetime):
# 如果是datetime类型的,返回一个datetime类型的字符串格式化输出
return field.strftime('%Y-%m-%d %H:%M:%s')
elif isinstance(field,date):
# 如果是date类型的,返回一个date类型的字符串格式化输出
return field.strftime('%Y-%m-%d')
else:
# 如果不是date、datetime类型的,就用父类的方法
return json.JSONEncoder.default(self,field)
d1 = datetime.Now()
json_str = json.dumps(d1,cls=JsonCustomEncoder)
print(json_str) # "2019-07-29 21:08:25"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。