axios数据发送与后台响应
在写vue项目时,肯定会用到的就是axios。我们可以通过axios将数据从后台读取然后也可以进行数据的修改等操作。但对于没有经验的人来说,第一次使用axios的post时会出现很多意想不到的事情。下面我们通过几个简单的示例来探究以下到底如何玩转axios的数据发送。
1. 前期准备
首先,要能发送数据,那就必须先创建一个vue。下面是一个简单的例子。
<template>
<div>
<button @click="sendTo">111</button>
</div>
</template>
<script>
export default {
name: 'Test',
methods: {
sendTo () {
this.axios({
url: '/hello/',
method: 'post'
}).then(res => {
console.log('111')
}).catch(error => {
console.log('222')
})
}
}
}
</script>
注意:在axios内部是并没放置任何数据的,后面我们会仔细的讲解一下。
接下来就是配置router
const TestVue = () => import('@/views/Test')
{
path: '/test',
component: TestVue
},
最后就是在后台写一个hello视图函数
def hello(request):
print(111)
return JsonResponse({"hello": 'hello'})
到现在为止,我们的前期工作也就完成了。
2. 实验开始
首先,我们看看这样的一个是否能调试成功

当我们按下111这个按钮之后,看下会发生什么。

可以看到,因为点击111按钮之后,我们的页面会自动跳转到后台。由于此时我们并没有发送任何数据,因此POST和body是没有任何数据的。这样的情况同样可以在开发者工具中发现。

这里并没有出现body部分。而出现两个hello/是因为第一个请求是OPTION的,查看该视图是否支持POST方法(具体的在跨域问题中已经讲过)。接下来,我们在axios中添加数据查看会发生什么。
2.1 直接在axios的data中添加相关的数据
this.axios({
url: '/hello/',
method: 'post',
data: {
'hello': 'hello',
'world': 'world'
}
})
同样的,我们还是打开页面,看看会出现什么。

很奇怪,我们并没有在POST属性中看到任何数据而是只在body中存在二进制的数据。我们在回到开发者工具中看看会是什么。

可这里明明是已经发送数据的。这是为什么呢?
2.2 post提交的四种编码方式
application/x-www-form-urlencoded
这应该是最常见的post编码方式,一般的表单提交默认以此方式提交。大部分服务器语言对这种方式都有很好的支持。而我们在项目中都基本上使用这种方式进行提交和获取。
multipart/form-data
这也是一种比较常见的post数据格式,我们用表单上传文件时,必须使form表单的enctype属性或者ajax的contentType参数等于multipart/form-data。使用这种编码格式时发送到后台的数据长得像这样子 .
不同字段以–boundary开始,接着是内容描述信息,最后是字段具体内容。如果传输的是文件,还要包含文件名和文件类型信息(后面会讲这个)
application/json
axios默认提交就是使用这种格式。如果使用这种编码方式,那么传递到后台的将是序列化后的json字符串。因此如果在django后台获取到我们输入的键值对,那就必须通过``json.loads`进行获取。
text/xml
因此,当我们了解到正常情况下,post使用json方式往后台传参数,那我们就可以直接使用json.loads函数将其解开,然后在使用。

没错,这样的确是一个很好的办法,但别忘了,POST是一个非常危险的方法,接触到POST方法的必定是需要对数据库进行操作的,因此这样的情况下如果直接使用body里面的内容很容易被居心叵测的人利用。因此,我们还是希望使用request.POST.get()进行获取对象,这样可行么?
2.3 使用application/x-www-form-urlencoded传输数据
答案是肯定的,当我们在传输数据的时候,我们可以将post的编码方式转化为application/x-www-form-urlencoded,这样就可以直接在后台获取到该键值对。例子如下。
this.axios({
url: '/hello/',
method: 'post',
data: {
'hello': 'hello',
'world': 'world'
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
可我们打开后台,发现POST虽然能拿到数据,但不是我们的键值对:

你可能会想到,会不会是因为data的键使用的是字符串,让他以为我们整个是字符串,我们要是直接变成一个变量呢?
this.axios({
url: '/hello/',
method: 'post',
data: {
hello: 'hello',
world: 'world'
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
结果还是一样,出现的是一整个作为键。

其实这个地方,我们需要使用一个parms来将我们需要传到后台的键值对进行收集,然后再发送。
let parms = new URLSearchParams()
parms.append('hello', 'hello')
parms.append('world', 'world')
this.axios({
url: '/hello/',
method: 'post',
data: parms,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
接下来,我们看看会发生什么

牛逼的事情出来了,我们再POST中已经形成了相应的键值对,而开发者工具中也进行了相应的变化。

所以,如果想前台传参进入后台,并不是直接在data中放置数据,你还必须设置post提交的编码方式和一个存放所有键值对的容器。
3. 文件传输
文件也是日常使用必不可少的东西,比如我们的更换头像、更换背景图片等。那这些东西也能通过刚才的编码方式进行传输么?答案是否定的。接下来我们继续探秘一下。
同样的,先写一个input,然后再data中存放一个file用来接收数据
<template>
<div>
<input type="file" v-model="file">
<button @click="sendTo">111</button>
</div>
</template>
<script>
export default {
name: 'Test',
data () {
return {
file: ''
}
},
methods: {
sendTo () {
let parms = new URLSearchParams()
parms.append('hello', 'hello')
parms.append('world', 'world')
parms.append('file', this.file)
this.axios({
url: '/hello/',
method: 'post',
data: parms,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(res => {
console.log('111')
}).catch(error => {
console.log('222')
})
}
}
}
</script>
当你写完这个,好家伙打开网页发现,一顿爆红,主要原因如下:

这是因为还是按照原本的思路使用v-model是不行的,需要@change
<input type="file" @change="file">
所以我们改完之后再次发起请求,看看会出现什么:

很奇怪,file里面并没有我们想要的数据,其实这是因为你不能直接使用file去获取该对象,而是应该使用一个函数去一次获取files内部的值然后添加进去。
<template>
<div>
<input type="file" @change="FileGet($event)">
<button @click="sendTo">111</button>
</div>
</template>
<script>
export default {
name: 'Test',
data () {
return {
file: ''
}
},
methods: {
sendTo () {
let parms = new URLSearchParams()
parms.append('hello', 'hello')
parms.append('world', 'world')
parms.append('file', this.file)
this.axios({
url: '/hello/',
method: 'post',
data: parms,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(res => {
console.log('111')
}).catch(error => {
console.log('222')
})
},
FileGet (event) {
let files = event.target.files
for (let i = 0; i < files.length; i++) {
this.file = files[i]
}
console.log(this.file)
}
}
}
</script>
此时,当我们配置好之后,将文件放入,然后再console就会出现file的相关信息。

嗯,非常不错。基本上的东西都完成了,那我们提交试试。当按下按钮之后,发现file里面是一个file对象

其实在外层还有一个FILES对象,文件将被存放在这里。但我们发现这里面并没用任何的数据。

还记得post提交的四种方式么?我们的文件并不适合application/x-www-form-urlencoded而因该使用multipart/form-data进行传输。因此我们还是需要再次进行修改。并且需要将容器修改成FormData
sendFile () {
let formData = new FormData()
formData.append('hello','hello')
formData.append('world','world')
formData.append('file',this.file)
this.axios({
url: '/hello/',
method: 'post',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' }
}).then(res => {
console.log(111)
}).catch(error => {
console.log(222)
})
}
配置完成以后,我们就可以来玩file了。

简单的方法
- 获取文件名:
request.FILES.get('file', '').name.split('.')

- 保存文件
def hello(request):
file_obj = request.FILES.get('file', '')
if file_obj:
# 更改名字,将原来的名字改为summer.原来的后缀名
file_name = "summer." + '.'.join(file_obj.name.split('.')[1:])
with open(os.path.join('./static/file', file_name), 'wb') as w:
for block in file_obj.chunks():
w.write(block)
return JsonResponse({"hello": 'hello'})
4. 日期小bug
在写日期的时候,我们前端使用日期选择器获取到的日期是一个中英文参杂的字符串,因此这样传入到后台是无法处理的。因此我们需要用到monent
<div>
<input type="file" @change="FileGet($event)">
<bk-date-picker v-model="initDateTime" :placeholder="'选择日期时间'" :type="'datetime'"></bk-date-picker>
<button @click="sendDate">111</button>
</div>
<script>
sendDate () {
console.log(this.initDateTime)
}
</script>
当我们写好这个之后,页面上的确出现的是我们想要的格式。

但我们获取initDateTime数据查看却发现该数据不是这样的

因此,为了获得我们想要的日期格式,我们就需要使用monent
import moment from 'moment'
sendDate () {
console.log(this.initDateTime)
let time = moment(this.initDateTime).format("YYYY-MM-DD hh:mm:ss")
console.log(time)
}

至此也就全部完成了。
本文详细介绍了axios在vue项目中的数据发送,包括post请求的四种编码方式、文件传输和日期格式化处理。通过实例解析了如何正确设置数据传输格式,确保数据能正确到达后台。

834

被折叠的 条评论
为什么被折叠?



