Django与Vue前后端交互的跨域问题

一、问题背景

之前有一个用Django框架写的网站,前端贪图方便直接用html+css写的,自然很丑,于是后来使用Vue框架+Element-ui组件来重构前端,使得网站前后端分离。

如何组合Django后端和Vue前端,我参考的是这篇博客整合 Django + Vue.js 框架快速搭建web项目,写的非常好,完整讲述了如何在Django项目中新建Vue项目,如何进行Django与Vue间的数据交互,以及如何将二者整合在一起。但是在“Django与Vue间的数据交互”这一部分,我踩了一个坑“No ‘Access-Control-Allow-Origin’ header is present on the requested resource. ”

在这里插入图片描述

文章中说这是因为Django和Vue运行的端口号不同,跨域问题,也给出了解决方法,但是写的十分简洁,而且用上去也还是没有解决到这个问题,于是我网上查了很久,试了很多方法,最终才解决了这个问题。下面详细讲解如何解决这个问题。

二、跨域问题

当开发模式采取前后端分离式开发时,通常情况下,前端和后端是运行不同的ip或者port下分别进行开发的,这就会导致出现跨域问题。跨域问题是因为浏览器有同源策略的限制,不是同源的脚本不能操作其他源下面的对象。

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

简单的来说:协议、IP、端口三者都相同,则为同源

clipboard.png

所以在本地开发项目时,Django后端运行在http://127.0.0.1:8000,而Vue前端运行在http://127.0.0.1:8080上,二者端口号不同,不同源,因此产生了跨域问题。

三、解决跨域问题的方法

网上主要有两种解决方法,分别是在前端解决和在后端解决。参考Django+vue跨域问题解决

前端解决跨域问题

参考vue2.0 proxyTable配置,解决跨域 webpack+vue-cil 中proxyTable配置接口地址代理 【vuejs开发】如何在vue里面优雅的解决跨域,路由冲突问题!超详细

既然跨域是因为不同源,那我同源不就完事儿了,但是后端请求地址不可能改变,所以可以在前端和后端的中间加一层代理(代理与后端是同源的),前端通过代理访问后端。

首先我的Vue前端的当前网页的地址是http://127.0.0.1:8080/JieHe_NetData,我要向Django后台请求数据的地址是http://127.0.0.1:8000/api/showdata?disease=JieHe

webpack配置vue 的 proxyTable解决跨域的解决方法是打开Vue项目的config目录下的index.js 文件,proxyTable中加入以下内容:

proxyTable: {
      '/api': {
        target: 'http://127.0.0.1:8000/',
        changeOrigin: true,
        // pathRewrite: {
        //   '^/api': ''
        // }
      }
    },
  • ‘/api’表示以’/api’开头的路径均需要代理,
  • target:代理的目标服务器地址(即后端服务器地址)为 ‘http://127.0.0.1:8000/’,
  • changeOrigin,为修改源:修改请求中的源地址
  • pathReWrite:URL路径重写,对于以’/api’开头的路径将’/api’替换为’’

这个配置的意思是,当我的请求地址http://127.0.0.1:8000/api/showdata?disease=JieHe中包含有/api路径时,就触发代理,相当于变成由http://127.0.0.1:8000/这个地址的代理主机发送这个请求,这样自然就能不会产生跨域问题了。注意这里我没有写pathRewrite,因为我的路径本身就是带有api的,我所有向后台请求数据的接口都带有api,不需要替换掉。

后端解决跨域问题

参考Django+vue跨域问题解决

后端出于安全考虑,有跨域限制,可以这样配置来取消这个限制:

安装django-cors-headers

pip install django-cors-headers

配置Django的settings.py文件

INSTALLED_APPS = [
    ...
    'corsheaders'...
 ] 

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware', # 注意顺序
    ...
)
#跨域增加忽略
CORS_ORIGIN_ALLOW_ALL = True

四、我解决问题的具体过程

然而我分别尝试了以上两种方法,都没有解决问题。后来我把Vue的请求地址从http://127.0.0.1:8000/api/showdata?disease=JieHe换成http://localhost:8000/api/showdata?disease=JieHe后竟然就解决了问题?我仍未想明白这到底是什么原理。而且我要同时用上前端和后端的方法才行,缺一不可,这个也没想明白为什么。

localhost与127.0.0.1的区别:

localhost:不通过网卡传输,不受网络防火墙和网卡相关的限制。

127.0.0.1:通过网卡传输,依赖网卡,并受到网卡和防火墙相关的限制。

localhost访问时,系统带着本机当前的用户权限去访问,而用ip的时候,等于本机是通过网络再去访问本机,可能涉及到网络用户的权限。所以一般设置程序是localhost是最好的,localhost不会解析成ip也不会占用网卡,网络资源。

另外,我也明白一个道理,就是一般设置程序是localhost是最好的,localhost不会解析成ip也不会占用网卡,网络资源。

下面再详细记录一下我解决问题的整个过程:

首先我Vue前端页面的请求是这样的:

export default {
  data () {
    return {
      message: "样例"
    }
  },
  mounted: function() {
    this.get_data_from_backend()
  },
  methods: {
    get_data_from_backend () {
         this.$http.get('http://localhost:8000/api/showdata?disease='+'JieHe')
            .then((response) => {
                var res = JSON.parse(response.bodyText)
                window.console.log(res)
            })
    },
  }
}

Django后端view.py中对应的处理函数的返回数据是这样的:

def showdata(request):
    disease = request.GET.get('disease')
    print('disease1=', disease)
    key_list, value_list = getNetData(disease)
    xList=key_list
    yList=value_list
    return JsonResponse({'disease': json.dumps(disease),
                                            'xList': json.dumps(xList),
                                            'yList': json.dumps(yList),
                                            'disease_name':disease} )

用Get方式请求数据。

首先是后端方面安装django-cors-headers,然后修改seeting.py

在这里插入图片描述

然后前端方面,修改config/index.js

在这里插入图片描述

然后就能成功请求数据了,F12打开console:

在这里插入图片描述

发布了131 篇原创文章 · 获赞 12 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_41519463/article/details/103842779
今日推荐