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导致的。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41337100/article/details/106161104