Django补充
CSRF_Token在页面中存放的几个位置
1. 在form表单中
<form action="" method="post"> {% csrf_token %} {# 这样后端就会把csrf_token的值渲染到这,形成一个input的隐藏标签 #} {# 标签的name值为csrfmiddlewaretoken #} </form>
形成的具体的隐藏标签如下
2. 在ajax中
如果是把csrf_token放在ajax中,有以下两个地方可以放入
a. 在ajax属性的headers中
$.ajax({ url:"", //不写代表向当前路径发送请求 type:"post", headers:{"X-CSRFToken":"{{ csrf_token }}"}, //这里必须放在引号中,不然会被当成变量去找值 data:{"name":"sss"}, success:function (data) { } })
b. 在ajax属性的data中
$.ajax({ url: "", type: "post", data: {"name":"sss", "csrfmiddlewaretoken": "{{ csrf_token }}"} success: function (data) { } })
前后端传输数据的编码格式
前后端传输数据的编码格式主要有三种
1. urlencode编码,也是form表单和ajax默认的编码格式,用来传输一些字符信息
2. formdata编码,主要是用来传输文件的编码格式
3. application/json编码, 传送json格式的字符编码,ajax里才有
下面分别通过form表单和ajax来讲解三个编码格式
特别需要注意的是:request.POST只能解析urlencoded编码格式的数据(formdata如果
发送字符串信息也会被放到POST中)
form表单中
前端代码,由于默认是urlencode编码格式,所以不写,那我们为什么知道默认是这个呢
看一个测试,条件是不写编码格式发送post请求,查看网页中的编码格式
我们可以看出,当我们不设置是,默认的content-type就是urlencoded
<form action="/app02/test/" method="post"> {% csrf_token %} <p>username:<input type="text" name="username"></p> <p>password:<input type="password" name="password"></p> <p><input type="file" name="myfile"></p> <p><input type="submit"></p> </form>
后端代码
# 后端接收数据代码 def test(request): if request.method == "POST": # 当前端是urlencoded编码格式时 print(request.POST) print(request.FILES) """ <QueryDict: {'csrfmiddlewaretoken': ['tcg1gkqE6eRRfZ0qW74YhMmdqU86qtwqBo0iiudlf3LqVGBHcDP3Jo8hPIwxYU2q'], 'username': ['hsdn'], 'password': ['sd'], 'myfile': ['微信图片_20190714181534.jpg']}> <MultiValueDict: {}> """ # 我们可以看出即使你传入了一个文件,也只会以字符串的形式把文件名传过来 # 当前端是formdata编码格式时 """ <QueryDict: {'csrfmiddlewaretoken': ['p21tUBHwMs4TH0q7lQPYo6hDst6QxM6zxeLKWLudVhYsnH1oBmA3QI3HRhuh5dCz'], 'username': ['1123'], 'password': ['sd']}> <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 微信图片_20190714181534.jpg (image/jpeg)>]}> """ # 我们可以看到,文件不会被request.POST解析,而是被request.FILES解析 # 我们可以把文件对象取出来然后操作 return render(request, "blog-code.html")
ajax中
1. urlencoded编码格式
$('#btn').click(function () { $.ajax({ url:"", type:"post", headers:{"X-CSRFToken":"{{ csrf_token }}"}, data:{ "username":$(".username").val(), "password":$(".password").val(), "myfile":$(".myfile").val() }, success:function (data) { alert(data) } }); })
后端代码
if request.method == "POST": # 当前端是urlencoded编码格式时 print(request.POST) print(request.FILES) """ <QueryDict: {'username': ['asdsad'], 'password': ['sdsd'], 'myfile': ['C:\\fakepath\\微信图片_20190714181534.jpg']}> <MultiValueDict: {}> """ # 我们可以看到,文件的路径被以字符串的形式被传了过来
2. formdata编码格式
$('#btn').click(function () { //用ajax传文件需要使用内置对象FormData let formData = new FormData(); //生成一个内置对象 //内置对象既可以放入普通的键值对,也可以放入文件 formData.append("username",$(".username").val()); formData.append("password",$(".password").val()); //想要取出文件对象,我们需要先把jq对象转成js对象,再根据.files取出文件对象 let fileObj = $('.myfile')[0].files[0]; formData.append("myfile", fileObj); $.ajax({ url:"", type:"post", //用ajax传文件需要加入以下两个参数 contentType:false, processData:false, headers:{"X-CSRFToken":"{{ csrf_token }}"}, data:formData, success:function (data) { alert(data) } }); })
后端代码 def test(request): if request.method == "POST": # 当前端是formdata编码格式时 print(request.POST) print(request.FILES) print(request.FILES.get("myfile").name) """ <QueryDict: {'username': ['撒旦第'], 'password': ['sdsd']}> <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 微信图片_20190714181534.jpg (image/jpeg)>]}> 微信图片_20190714181534.jpg """ # 后端代码我们可以看出来,字符串的数据被解析到POST中,文件数据被解析到FILES中 # 并且我们可以通过文件对象.name 拿出文件名 # 写到本地中 with open(request.FILES.get("myfile").name, 'wb') as f: for line in request.FILES.get("myfile"): f.write(line) # 这个文件对象就相当于f对象,可以for line 把每一行取出来
3. application/json编码格式
$('#btn').click(function () {
//发送json格式的时候需要stringify以下
$.ajax({
url:"",
type: "post",
headers:{"X-CSRFToken":"{{ csrf_token }}"},
contentType: "application/json"
data: JSON.stringify({"username":$(".username").val()}),
success: function (data) {
alert(data)
}
})
});
后端代码
if request.method == "POST": # 当前端是json编码格式时 print(request.POST) print(request.body) """ <QueryDict: {'{"username":"sd"}': ['']}> b'{"username":"sd"}' 我们可以看到,request.POST已经不是我们之间常见那种形式的对象, 他是把整个二进制字符串当成了一个key 而我们真正的json字符串则是被保存到了request.body中 实际上,当请求编码为json时,后端是不会对我们数据进行操作的 是整体放到body中,我们可以取出来反序列化 """