由於瀏覽器同源策略的限制(同一主機不同端口之間),會產生客戶端向服務端請求存在跨域的問題,如向服務端發送獲取數據的請求,客戶端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<button @click="getUser">獲取用戶信息</button>
<ul>
<li v-for="(item,index) in users">{{item}}</li>
<li v-for="(item,index) in users">{{item.id}}</li>
<li v-for="(item,index) in users">{{item.name}}</li>
<li v-for="(item,index) in users">{{item.register_date}}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
<script>
new Vue({
el: '#app',
data: {
apiDomain: 'http://localhost:8000/api/v1',
users: []
},
methods: {
getUser() {
let self = this
axios.get(`${this.apiDomain}/user/`).then(function (response) {
self.users = response.data.data
console.log(response)
}).catch(function (error) {
console.log(error)
})
}
}
});
</script>
</html>
服務端:
from rest_framework import views, serializers, response
from .. import models
class UserSerializer(serializers.ModelSerializer):
name = serializers.CharField(max_length=5, error_messages={'max_length': '字段太長!'})
register_date = serializers.DateTimeField(format='%Y-%m-%d %X')
class Meta:
model = models.User
fields = ('name', 'register_date', 'id')
class User(views.APIView):
def get(self, request):
qs = models.User.objects.all().first()
serializer = UserSerializer(qs, many=False)
return response.Response({
'status': 0,
'data': serializer.data
})
當點擊獲取數據的按鈕後,報錯:
這時候可以在Django中寫中間件,通過修改 response的屬性允許這個域的請求
來解決:
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
def process_response(self, request, response):
response['Access-Control-Allow-Origin'] = '*'
return response
記得需要在配置文件中配置這個中間件:
MIDDLEWARE = [
...
'app.middle.M1'
]
這個時候就可以成功獲取數據:
再看下提交數據的請求:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<button @click="getUser">獲取用戶信息</button>
<button @click="createUser">創建用戶信息</button>
<ul>
<li v-for="(item,index) in users">{{item}}</li>
<li v-for="(item,index) in users">{{item.id}}</li>
<li v-for="(item,index) in users">{{item.name}}</li>
<li v-for="(item,index) in users">{{item.register_date}}</li>
</ul>
</div>
</body>
<script src="js/vue.js"></script>
<script src="js/axios.js"></script>
<script>
new Vue({
el: '#app',
data: {
apiDomain: 'http://localhost:8000/api/v1',
users: []
},
methods: {
getUser() {
let self = this
axios.get(`${this.apiDomain}/user/`).then(function (response) {
self.users = response.data.data
console.log(response)
}).catch(function (error) {
console.log(error)
})
},
createUser() {
let self = this
axios.post(`${this.apiDomain}/user/`, {"name": 'Thanlon'}).then(function (response) {
console.log(response)
}).catch(function (error) {
console.log(error)
})
}
}
});
</script>
</html>
發送POST請求提交數據的時候,客戶端報錯竟然也報跨域問題。根據報錯提示,這是不允許請求頭引起的,所以需要配置允許的請求頭Access-Control-Allow-Headers:
並且服務端報錯:
這是因爲一般跨域會出現預檢請求,瀏覽器會認爲這是一次複雜的請求,會先發一個請求做預檢。預檢請求響應的狀態是200的時候纔會發真正的請求。所以,還需要在 中間件中設置允許的方法
:
from django.utils.deprecation import MiddlewareMixin
class M1(MiddlewareMixin):
def process_response(self, request, response):
# 允許請求的域
response['Access-Control-Allow-Origin'] = '*'
# 允許請求的請求頭
response['Access-Control-Allow-Headers'] = '*'
# 允許請求的方法,適用*是允許所有,還可以指定。需要用都好隔開,例如'OPTIONS,GET,POST',實測發現這裏不需要也是可以的
# response['Access-Control-Allow-Methods'] = 'OPTIONS'
return response