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:

在這裏插入圖片描述

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