Django+Vue+微信登录授权前后端分离实现过程中踩坑问题阶段性总结

首先,关于Django+Vue前后端分离介绍
请参考
使用Django + Vue.js快速而优雅地构建前后端分离项目
或者
使用Django + Vue.js快速而优雅地构建前后端分离项目

关于Vue的使用请参考
Vue.js官方网站

我要说明的是另外以下几点:

  1. 跨域问题
    关于跨域问题是指在开发前端页面使用前端热更新调试过程中与Django进行的数据请求产生的跨域问题.
    例如你在本地
    http://localhost:8080/#/
    调试界面请求Django本地服务器
    http://localhost:8000/
    下的Api数据时就会产生跨域问题,因为端口号不一致.
    解决跨域问题需要前端后端同时解决.
    前端:
    a. 在config目录下的index.js中dev下找到proxyTable
    Django+Vue+微信登录授权前后端分离实现过程中踩坑问题阶段性总结_第1张图片
    修改为如图代码如下

    '/apis': {//此处/apis并不需要保持一致.
                // 测试环境
                target: 'http://localhost:8000',  // 接口域名
                changeOrigin: true,  //是否跨域
                pathRewrite: {
                    '^/apis': ''   //需要rewrite重写的,
                }
            }
    

    b.修改config/dev.env.js文件添加

    API_ROOT: '"/apis"'
    

    Django+Vue+微信登录授权前后端分离实现过程中踩坑问题阶段性总结_第2张图片
    修改config/prod.env.js

    API_ROOT: '"你自己的生产发布地址"'
    

    c.你原始请求Django数据的url
    ‘http://localhost:8000/api/testApi’
    修改为
    process.env.API_ROOT + ‘/api/testApi’
    当然你也可以直接设置axios的baseURL为process.env.API_ROOT
    后端:
    Django可以使用第三方包 django-cors-headers 来解决跨域问题,具体操作如下:
    a. cd 到Django项目文件夹
    b. 执行 python pip install django-cors-headers安装django-cors-headers
    c. settings.py 新增加星号那一行,注意中间件加载顺序,列表是有序的。

    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',
    ]
    

    在下面再新增

    CORS_ORIGIN_ALLOW_ALL = True
    
  2. 前后端项目目录结构问题
    在Django中以及在Vue中都有各自的静态文件存放路径,假如我们上生产的时候想把所有静态文件都放在一起以方便静态文件的转发与搜索的话,例如可以放在Django的statics静态文件夹中.
    需要修改我们build出来的
    Django+Vue+微信登录授权前后端分离实现过程中踩坑问题阶段性总结_第3张图片
    修改之后再build你会发现
    目录结构的变化
    Django+Vue+微信登录授权前后端分离实现过程中踩坑问题阶段性总结_第4张图片
    那么我们在setting.py中静态文件搜索路径中的前端路径就不需要了Django+Vue+微信登录授权前后端分离实现过程中踩坑问题阶段性总结_第5张图片

  3. 进入页面需要微信登录授权问题
    如果我们要开发微信公众号等微信相关页面时,进入前端页面需要微信授权的情况下,可以使用在这里插入图片描述
    其实一开始我遇到了一个问题:进入界面的时候没有使用装饰器,在请求Api的时候对Api使用了装饰器,当第一次请求授权成功之后因为装饰器中跳转链接是使用redirect_url = request.get_raw_uri()获取当前访问的链接进行跳转所以授权成功之后不是进入到访问页面而是会显示Api成功的response应答数据.当我收到301进行字符串截取替换的过程中,发现授权页面一直在不停的循环跳转.不知道什么原因???

  4. axios封装问题

    import axios from 'axios'
    
    // axios默认公共参数
    const http = axios.create({
    	baseURL: process.env.API_ROOT,
    	timeout: 10000,
    	withCredentials: true, // 跨域
    	headers: {
    		'X-Requested-With': 'XMLHttpRequest',
    		'Cache-Control': 'no-cache',
    	},
    });
    
    let cancel, promiseArr = {}
    const CancelToken = axios.CancelToken;
    //请求拦截器
    http.interceptors.request.use(config => {
    	//发起请求时,取消掉当前正在进行的相同请求
    	if (promiseArr[config.url]) {
    		promiseArr[config.url]('操作取消')
    		promiseArr[config.url] = cancel
    	} else {
    		promiseArr[config.url] = cancel
    	}
    	return config
    }, error => {
    	return Promise.reject(error)
    })
    
    http.interceptors.response.use(response => {
    		let {
    			status,
    			statusText,
    			data
    		} = response;
    		if (err_check(status, statusText, data) && data) {
    			return Promise.resolve(data);
    		} else {
    			return Promise.reject(data);
    		}
    	},
    	err => {
    		if (axios.isCancel(err)) {
    			err.response = {
    				status:100,
    				statusText:err.message
    			}
    		}
    		else if (err && err.response) {
    			switch (err.response.status) {
    				case 400:
    					err.message = '错误请求';
    					break;
    				case 401:
    					err.message = '未授权,请重新登录';
    					break;
    				case 403:
    					err.message = '拒绝访问';
    					break;
    				case 404:
    					err.message = '请求错误,未找到该资源';
    					break;
    				case 405:
    					err.message = '请求方法未允许';
    					break;
    				case 408:
    					err.message = '请求超时';
    					break;
    				case 500:
    					err.message = '服务器端出错';
    					break;
    				case 501:
    					err.message = '网络未实现';
    					break;
    				case 502:
    					err.message = '网络错误';
    					break;
    				case 503:
    					err.message = '服务不可用';
    					break;
    				case 504:
    					err.message = '网络超时';
    					break;
    				case 505:
    					err.message = 'http版本不支持该请求';
    					break;
    				default:
    					err.message = `连接错误${err.response.status}`;
    			}
    		} else {
    			err.message = "连接到服务器失败";
    		}
    		console.log('err.message:',err.message);
    		return Promise.reject(err.response)
    	})
    
    const err_check = (code, message, data) => {
    	if (code == 200) {
    		return true
    	}
    	return false
    }
    
    export default {
    	httpRequest(method, url, param) {
    		return new Promise((resolve, reject) => {
    			http({
    				method,
    				url,
    				data: param,
    				cancelToken: new CancelToken(c => {
    					cancel = c
    				})
    			})
    			.then(res => {
    				resolve(res)
    			})
    			.catch(err => {
    				reject(err)
    			})
    		})
    	},
    	cancelRequest(msg){
    			// 第一次执行cancelRequest()时可能还未发送请求,会报错,添加如下判断
    	  if (typeof cancel === 'function') {
    	    // 取消请求
    	    cancel(msg)
    	  }
    	}
    }
    
    
  5. axios使用post请求后端无法获取数据问题
    安装qs,在 main.js里引入

    import qs from 'qs';
    Vue.prototype.$qs = qs;
    

    在vue组件里面请求方法

    let postData = this.$qs.stringify({
        key1:value1,
        key2:value2,
    });
    this.$axios({
        method: 'post',
        url:'url',
        data:postData
    }).then((res)=>{
        
    });
    

    参考axios 使用post方式传递参数,后端接受不到

  6. axios取消重复请求

    let cancel, promiseArr = {}
    const CancelToken = axios.CancelToken;
    //请求拦截器
    http.interceptors.request.use(config => {
    	//发起请求时,取消掉当前正在进行的相同请求
    	if (promiseArr[config.url]) {
    		promiseArr[config.url]('操作取消')
    		promiseArr[config.url] = cancel
    	} else {
    		promiseArr[config.url] = cancel
    	}
    	return config
    }, error => {
    	return Promise.reject(error)
    })
    

    参考
    vue项目中对axios的二次封装
    以上代码与参考略有完善

  7. 引入外部JS样式问题例如微信样式weui
    a.安装 weui, 并在 main.js 中导入weui.min.css

    npm install --save weui // 安装weui
    
    import 'weui/dist/style/weui.min.css' // 在main.js中导入weui.min.css
    

    b.在我们项目的vue文件中 引入 weui 的UI布局

    
    
  8. background-image图片路径问题
    参考vue踩坑系列——backgroundImage路径问题
    但是我发现我放到Django中statics下的图片依然可以访问成功

    // cardInfo.cardImage为Django目录下的路径:/statics/image/common/cards/card-sptcc.png
    backgroundImage: 'url(' + cardInfo.cardImage + ')'
    
  9. axios返回缓存问题(from disk cache)
    axios请求头中新增’Cache-Control’: ‘no-cache’,

    headers: {
    		'X-Requested-With': 'XMLHttpRequest',
    		'Cache-Control': 'no-cache',
    	},
    
  10. Vue前进刷新后退不刷新问题(TODO)
    参考另辟蹊径:vue单页面,多路由,前进刷新,后退不刷新

  11. vue prod 环境 怎么去掉#
    参考vue prod 环境 怎么去掉#!

  12. Django经过微信授权后带各种参数的url第一次路由到Vue时,Vue路由直接直接拼接path问题.
    例如:Django下url.py中

    url('frontend', wx_login_required(TemplateView.as_view(template_name="index.html"))),
    

    Vue下router中

    {
          name: 'login',
          path: '/login',
          component: Login
     }
    

    可能你想要得到的链接是这样的

    http://ip:port/frontend/login?appId=你的
    

    但是当你按照这样的地址输入时却不显示任何组件内容.你就很奇怪了,于是经过redirect你发现经过Django装饰器的微信授权之后实际地址确实这样的.

    http://ip:port/frontend/login?appId=你的&code=&state=STATE#/login
    

    问题描述:由于vue使用vue-router时,路径中会有#的字段导致的.在地址栏中不存在#所以路由会不识别改地址,重定向的时候会直接在后面添加#/地址.
    目前解决方案的思路
    1.前端去除# : 使用router的history模式, 且在服务器端进行配置
    参考:问题11
    2.使用JSSDK进行前端授权
    参考Vue:在Vue中实现微信网页授权和分享

你可能感兴趣的:(日常日志,Django,Vue,Vue微信授权,Django,Vue,jssdk,Django,Vue,微信,Django,Vue前后端分离)