vue-cli3使用axios請求後端(Python+Django)的數據和跨域proxy設置踩坑指南

注意:我是負責前端部分的,後端是同學在負責,所以我只負責一個前後端的對接。背景是一個在線商城。

前端部分

首先清楚前端是作爲客戶端,請求後端服務端的消息。所以前端後端都run起來。
後端的同學給了我這樣的接口文檔:
在這裏插入圖片描述
因此後端請求這個url就能夠返回數據:
在這裏插入圖片描述
接下來是前端的問題,前端就是要向這個URL發出get的請求。
這裏我使用了axios的包,首先npm install axios,然後在/src/api/index.js下對axios做配置:

import axios from 'axios';
import Qs from 'qs'; // 用來處理參數,可不使用,若要使用,npm安裝: npm install qs
axios.defaults.baseURL = 'http://127.0.0.1:8000/'; // 請求的默認域名
// 添加一個請求攔截器
axios.interceptors.request.use(config => {
        config.headers.languagetype = 'CN'; // 舉例,加上一個公共頭部
        config.data = Qs.stringify(config.data); // 處理數據,可不寫
        return config;
    },
    err => {
        return Promise.reject(err);
    });

//添加一個響應攔截器
axios.interceptors.response.use(res => {
    //在這裏對返回的數據進行處理
    console.log(res.data, '網絡正常');
    return res.data;
}, err => {
    console.log('網絡開了小差!請重試...');
    return Promise.reject(err);
});

export default axios 

然後在main.js的地方全局引入,注意這裏的axios是灰色的,因爲Unused definition $axios,但是無所謂:

Vue.prototype.$axios = Axios; //全局註冊,使用方法爲:this.$axios
Vue.config.productionTip = false;

接下來就可以在任何一個vue中直接通過this.$axios引用了:

        methods:{
            //params是添加到url的請求字符串中的,用於get請求, 參數是以id=124&name=jerry的形式附到url的後面
            // 而data是添加到請求體(body)中的, 用於post請求。
            test(){
                this.items = this.$axios({
                    method: "get",
                    url: "/goods/ListItem", // 接口地址
                    // data: {
                    //     keyword: "1"   // 傳接口參數
                    // }
                })
                    .then(response => {
                        console.log(response, "success");   // 成功的返回
                    })
                    .catch(error => console.log(error, "error")); // 失敗的返
            }
        }

但是此時有一個很嚴重的錯誤發生了,作爲服務器的Django和vue產生了一個跨域的問題,瀏覽器禁止跨域訪問:
Access to XMLHttpRequest at 'http://127.0.0.1:8000/goods/ListItem' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
我一開始天真的認爲改變一下vue服務器的端口就行,於是在根目錄下創建了vue.config.js,想把軟口也設置成8000,但是8000其實已經被Django佔用了,所以會自動改成8001端口,所以跨域問題是必須要解決的了:

module.exports = {
    devServer: {
        disableHostCheck: true,
        host:'127.0.0.1',
        port: 8000,
    },
    lintOnSave: false
}

在這裏插入圖片描述
於是我修改成這樣,但是即使這樣還是會報404,並且還是用本地的地址:
在這裏插入圖片描述
中間經歷了幾天的波折才弄懂。
首先main.js一定要引入baseURL,如果不引入或者爲空Django的服務器端是無法收到請求的:

axios.defaults.baseURL = '/goods';

然後vue.config.js裏面配置,注意我這裏是proxy而不是proxytable。host和port都是設置vue端的服務器地址和端口。

module.exports = {
    devServer: {
        host: '127.0.0.1',
        port: 8080,
        open: true,
        proxy: {//配置跨域
            '/goods': {
                target: 'http://127.0.0.1:8000',//這裏後臺的地址,應該填寫你們真實的後臺接口
                ws: true,
                secure: false,//https則是ture
                changOrigin: true,//允許跨域
                // pathRewrite: {
                //     '^/goods': ''
                // }
            },
        }
    }
};

然後使用axios在組件中實現跨域,我要訪問的具體地址是http://127.0.0.1:8000/goods/ListItem:

            this.axios.get("/goods/ListItem")
                .then(response => {
                    if (response.data) {
                        console.log(response.data)
                    }
            })
                .catch(error => {
                    alert(error)
                })

axios踩坑的錯誤寫法:

  • 第一種:多寫了pathRewrite。
    配置部分:
module.exports = {
    devServer: {
        host: '127.0.0.1',
        // NODE_ENV: 'production',//生產環境
        port: 8080,
        open: true,
        proxy: {//配置跨域
            '/goods': {
                target: 'http://127.0.0.1:8000',//這裏後臺的地址模擬的;應該填寫你們真實的後臺接口
                ws: true,
                secure: false,
                changOrigin: true,//允許跨域
                pathRewrite: {
                    '^/goods': ''
                }
            },
        }
    }
};

main.js:

axios.defaults.baseURL = '/goods';

使用:

 this.axios.get("/goods/ListItem")

此時後臺接受的消息顯然是將使用的/goods替換成了’ '。雖然看起來應該是baseurl+/goods/ListItem,但是實際上顯然baseurl被替換成了proxy下的/goods的target。

  • 那按道理來說這裏配置代理可以不設置成/goods,而設置成別的也行,比如我設置了一個/api,自動被識別成代理,然後和get的拼接起來。但是實際上是不可以的。無聊pathrewrite是否被註釋都不可以。
axios.defaults.baseURL = '/api';
module.exports = {
    devServer: {
        host: '127.0.0.1',
        // NODE_ENV: 'production',//生產環境
        port: 8080,
        open: true,
        proxy: {//配置跨域
            '/api': {
                target: 'http://127.0.0.1:8000',//這裏後臺的地址模擬的;應該填寫你們真實的後臺接口
                ws: true,
                secure: false,
                changOrigin: true,//允許跨域
                // pathRewrite: {
                //     '^/goods': ''
                // }
            },
        }
    }
};
this.axios.get("/goods/ListItem")

也就是說,想要代理成功,必須代理的地址必須和代理的api一致才行。比如我要訪問的是/goods/listitem/,我必須設置的代理是/goods。

後端部分

接下來是對Django的設置。首先先安裝conda install django-cors-headers
然後在settings.py裏修改配置。
在導入的模塊里加入corsheaders:

INSTALLED_APPS = [
    'store_db',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 跨域設計
    'corsheaders'
]

然後在中間件加入’corsheaders.middleware.CorsMiddleware’:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',  # 注意順序,必須放在這兒
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

最後加入:


#開啓debug模式,注意上線運營時要關閉debug
DEBUG = True

# 允許所有ip訪問
ALLOWED_HOSTS = ['*']

#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
if DEBUG:
    CORS_ORIGIN_ALLOW_ALL = True
else:
    CCORS_ORIGIN_WHITELIST = (
    //注意這裏不能加http
        '127.0.0.1:8080'
    )

# 允許的請求頭
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

曾經遇到這個問題就是CCORS_ORIGIN_WHITELIST中加了http導致的。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章