vue+rest-framework先後端分離整合(二)

1、基於api前端顯示課程詳細信息

一、調整Course.vue模塊

<template>
    <div>
        <h1>課程列表</h1>
        <div v-for="row in courseList">
            <div style="width:350px;float: left;">
                <!--<img src="" alt=""/>-->
                <h3><router-link :to="{name:'detail', params:{id:row.id}}">{{row.title}}</router-link></h3>
                <p>{{row.level}}</p>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "index",
        data() {
            return {
                courseList: []
            }
        },
        mounted: function () {
            // vue頁面剛加載時自動執行
            this.initCourse()
        },
        methods: {
            initCourse: function () {
                /*
                this.courseList = [
                  {id:1,title:'Python全棧'},
                  {id:2,title:'Linux運維'},
                  {id:3,title:'金融分析'},
                ]
                */

                // 經過ajax向接口發送請求,並獲取課程列表
                // axios 發送ajax請求
                // npm install axios --save
                // 第一步:在main.js中配置
                // 第二步:使用axios發送請求
                var that = this;

                this.$axios.request({
                    url: 'http://127.0.0.1:8000/api/v1/course/',
                    method: "GET"
                }).then(function (ret) {
                    // ajax請求發送成功後,獲取的響應內容
                    console.log(ret.data);
                    if (ret.data.code === 1000) {
                        // 注意這裏的this已經再也不是以前的this
                        that.courseList = ret.data.data
                    }else{
                        alert("獲取數據失敗");
                    }
                }).catch(function (ret) {
                    // ajax請求失敗以後,獲取響應的內容
                })
            }
        }
    }
</script>

<style scoped>

</style>

  顯示效果:javascript

  

二、調整Detail.vue模塊

<template>
    <div>
        <h1>課程詳細頁面</h1>
        <div>
            <p>{{detail.course}}</p>
            <p>{{detail.img}}</p>
            <p>{{detail.level}}</p>
            <p>{{detail.slogon}}</p>
            <p>{{detail.title}}</p>
            <p>{{detail.why}}</p>
            <div>
                <ul v-for="item in detail.chapter">
                    <li>{{item.name}}</li>
                </ul>
            </div>

            <div>
                <ul v-for="item in detail.recommends">
                    <li>{{item.title}}</li>
                </ul>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "index",
        data() {
            return {
                detail: {     // 定義字典和相關的key
                    course: null,
                    img: null,
                    level: null,
                    slogon: null,
                    title: null,
                    why: null,
                    chapter: [],
                    recommends: [],
                }
            }
        },
        mounted() {
            this.initDetail()
        },
        methods: {
            initDetail() {
                var nid = this.$route.params.id;    // 獲取當前id值(用於拼接url)
                var that = this;
                this.$axios.request({   // 發送axios請求
                    url: 'http://127.0.0.1:8000/api/v1/course/' + nid + '/',
                    method: 'GET'
                }).then(function (arg) {   // arg是返回的值:{code:1000, data:{...}}
                    // 將拿到的值賦值給detail
                    if (arg.data.code === 1000) {
                        that.detail = arg.data.data   // 注意這裏的this已經不是原來的this
                    } else {
                        alert(arg.data.error)
                    }
                })
            }
        }
    }
</script>

<style scoped>

</style>

  顯示效果:前端

  

2、推薦課程切換及詳情展現 

一、測試使用router-link是否合適

  對Detail.vue修改以下:vue

<template>
    <div>
        <h1>課程詳細頁面</h1>
        <div>
            <p>{{detail.course}}</p>
            <p>{{detail.img}}</p>
            <p>{{detail.level}}</p>
            <p>{{detail.slogon}}</p>
            <p>{{detail.title}}</p>
            <p>{{detail.why}}</p>
            <div>
                <ul v-for="item in detail.chapter">
                    <li>{{item.name}}</li>
                </ul>
            </div>

            <div>
                <h3>推薦課程</h3>
                <ul v-for="item in detail.recommends">
                    <li><router-link :to="{name:'detail',params:{id:item.id}}">{{item.title}}</router-link></li>
                </ul>
            </div>
        </div>
    </div>
</template>

  給推薦課程添加連接地址,點擊能夠實現url切換,可是因爲組件沒有從新加載,this.initDetail()沒有執行。java

  所以頁面的內容並不會發生切換。此方法不合適。python

二、添加點擊事件處理推薦課程點擊切換 

<template>
    <div>
        <h1>課程詳細頁面</h1>
        <div>
            <p>{{detail.course}}</p>
            <p>{{detail.img}}</p>
            <p>{{detail.level}}</p>
            <p>{{detail.slogon}}</p>
            <p>{{detail.title}}</p>
            <p>{{detail.why}}</p>
            <div>
                <ul v-for="item in detail.chapter">
                    <li>{{item.name}}</li>
                </ul>
            </div>

            <div>
                <h3>推薦課程</h3>
                <ul v-for="item in detail.recommends">
                    <!--爲推薦課程添加點擊事件-->
                    <li @click="changeDetail(item.id)">{{item.title}}</li>
                </ul>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "index",
        data() {
            return {
                detail: {     // 定義字典和相關的key
                    course: null,
                    img: null,
                    level: null,
                    slogon: null,
                    title: null,
                    why: null,
                    chapter: [],
                    recommends: [],
                }
            }
        },
        mounted() {
            var id = this.$route.params.id;    // 獲取當前id值(用於拼接url)
            this.initDetail(id)
        },
        methods: {
            initDetail(nid) {
                var that = this;
                this.$axios.request({   // 發送axios請求
                    url: 'http://127.0.0.1:8000/api/v1/course/' + nid + '/',
                    method: 'GET'
                }).then(function (arg) {   // arg是返回的值:{code:1000, data:{...}}
                    // 將拿到的值賦值給detail
                    if (arg.data.code === 1000) {
                        that.detail = arg.data.data   // 注意這裏的this已經不是原來的this
                    } else {
                        alert(arg.data.error)
                    }
                })
            },
            changeDetail(id){   // click拿到課程id從新加載就能夠渲染成功了
                this.initDetail(id);   // 切換頁面顯示
                this.$router.push({name: 'detail', params: {id:id}});  // 修改url地址
            }
        }
    }
</script>

<style scoped>

</style>

  注意:這裏將var id = this.$route.params.id; 操做提到了vue生命週期mounted方法中。所以initDetail(nid)函數接收的nid,有多是從mounted中傳遞過來的id也能夠是changeDetail傳遞的id。ios

  在 Vue 實例內部,你能夠經過 $router 訪問路由實例。所以你能夠調用 this.$router.pushajax

this.$router.push({name: 'detail', params: {id:id}});   // 命名的路由

  顯示效果以下所示:vuex

  

  點擊推薦課程能夠自由切換頁面路徑和頁面顯示。數據庫

3、用戶登陸功能實現

一、前端添加Login.vue模塊

(1)App.vue和index.js添加Login模塊

############# App.vue ###############
<template>
  <div id="app">
    <router-link to="/index">首頁</router-link>
    <router-link to="/course">課程</router-link>
    <router-link to="/micro">微職位</router-link>
    <router-link to="/news">深科技</router-link>
    <div>
        <router-link to="/login">登陸</router-link>
    </div>
    <router-view/>
  </div>
</template>


############# index.js ###############
import Login from '../components/Login'
Vue.use(Router);

export default new Router({
    routes: [
        // 其餘代碼省略
        {
            path: '/login',
            name: 'login',
            component: Login
        },
    ]
})

(2)Login.vue構建

<template>
    <div>
        <h2>用戶登陸</h2>
        <div>
            <p>
                <input type="text" placeholder="請輸入用戶名" v-model="username">
            </p>
            <p>
                <input type="password" placeholder="請輸入密碼" v-model="password">
            </p>
            <input type="button" value="登陸" @click="doLogin">
        </div>
    </div>
</template>

<script>
    export default {
        data(){
            return {
                // 經過v-model雙向綁定用戶名和密碼
                username:'',
                password:''
            }
        },
        methods: {
            doLogin(){
                this.$axios.request({
                    url:'http://127.0.0.1:8000/api/v1/auth/',
                    method:'POST',
                    data:{
                        user:this.username,
                        pwd:this.password
                    },
                    headers:{
                        'Content-Type': 'application/json'
                    }
                }).then(function (arg) {
                    // 拿回結果
                    console.log(arg)
                }).catch(function (arg) {
                    // 拿到錯誤信息
                    console.log("發生錯誤")
                })
            }
        }
    }
</script>

<style scoped>

</style>

  注意:這裏是經過v-model雙向綁定用戶名和密碼,並以此經過post請求來發送username和password。npm

二、django後臺auth接口配置

(1)路由配置api/urls.py:

urlpatterns = [
    """代碼省略"""
    url(r'^(?P<version>[v1|v2]+)/auth/$', account.AuthView.as_view()),

]

(2)視圖配置api/view/account.py:

from rest_framework.views import APIView
from rest_framework.response import Response

class AuthView(APIView):
    def post(self, request, *args, **kwargs):
        print(request.data)

        return Response('...')

(3)在前臺頁面嘗試登錄

  

  能夠看到雖然配置的是post請求,但實際卻發送的是OPTIONS請求

三、跨域問題處理

(1)簡單請求和非簡單請求

  瀏覽器將CORS請求分紅兩類:簡單請求(simple request)和非簡單請求(not-so-simple request)。

  只要同時知足如下兩大條件,就屬於簡單請求。

(1) 請求方法是如下三種方法之一:
HEAD
GET
POST
(2)HTTP的頭信息不超出如下幾種字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限於三個值application/x-www-form-urlencoded、multipart/form-data、text/plain

  凡是不一樣時知足上面兩個條件,就屬於非簡單請求。

  若是是複雜請求,會先用options請求進行預檢,經過以後才能發送post請求。

(2)配置修改account.py,添加options請求處理

from rest_framework.views import APIView
from rest_framework.response import Response
from django.shortcuts import HttpResponse

class AuthView(APIView):

    def options(self, request, *args, **kwargs):
        # 進行預檢
        obj = HttpResponse('')
        obj["Access-Control-Allow-Origin"] = "*"   # 容許你的域名來獲取個人數據
        obj['Access-Control-Allow-Headers'] = "Content-Type"  # 容許你攜帶Content-Type請求頭
        return obj

    def post(self, request, *args, **kwargs):
        print(request.data)

        # 同源策略禁止讀取位於 http://127.0.0.1:8000/api/v1/auth/ 的遠程資源。(緣由:CORS 頭缺乏 'Access-Control-Allow-Origin')
        obj = Response("...")
        obj["Access-Control-Allow-Origin"] = "*"   # 容許你的域名來獲取個人數據

        return obj  # 返回值再加上一個響應頭

  再次訪問登陸頁面,嘗試登陸操做,能夠看到OPTIONS請求經過後,發送POST請求,python後端也打印出request.data中的數據。

  

 (3)用中間件來處理跨域問題

  上面這種方式過於麻煩了,通常仍是交給中間件來處理跨域問題,爲全部請求都設置頭。

  /api/cors.py:

from django.utils.deprecation import MiddlewareMixin

class CORSMiddleware(MiddlewareMixin):
    """自定義中間件"""

    def process_response(self, request, response):
        # 添加響應頭

        # 容許你的域名來獲取個人數據
        response['Access-Control-Allow-Origin'] = "*"
        # 容許你攜帶Content-Type請求頭,這裏不能寫*
        # response['Access-Control-Allow-Headers'] = "Content-Type"
        # 容許你發送GET/POST/DELETE/PUT
        # response['Access-Control-Allow-Methods'] = "GET, POST"

        if request.method == "OPTIONS":
            response["Access-Control-Allow-Headers"] = "Content-Type"
        return response

四、rest-framework登陸驗證

(1)給models.py添加User和Token模型

class UserInfo(models.Model):
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=64)


class UserToken(models.Model):
    user = models.OneToOneField(to="UserInfo", on_delete=models.CASCADE)
    token = models.CharField(max_length=64)  # 不只能夠配置token,還能夠配置超時時間

  利用makemigrations和migrate完成數據遷移操做。在UserInfo表添加用戶和密碼。

(2)後端處理登陸信息,更新並建立token信息

  重寫/api/views/account.py以下所示:

from rest_framework.views import APIView
from rest_framework.response import Response
from django.shortcuts import HttpResponse
from api import models
import uuid   # 網卡和時間生成的隨機字符串

class AuthView(APIView):

    def post(self, request, *args, **kwargs):
        """
        用戶登陸認證
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        print(request.data)
        ret = {'code': 1000}
        # 用get方法取的話,不存在即爲Null
        user = request.data.get("user")
        pwd = request.data.get("pwd")
        user = models.UserInfo.objects.filter(user=user, pwd=pwd).first()
        if not user:
            ret['code'] = 1001
            ret['error'] = "用戶名或密碼錯誤"
        else:
            uid = str(uuid.uuid4())  # 將生成的隨機對象轉化爲隨機字符串
            models.UserToken.objects.update_or_create(user=user, defaults={"token":uid})
            ret["token"] = uid
        return Response(ret)

(3)登陸驗證

  在vue前端登陸,顯示信息以下:

  

  在python後臺打印request.data信息:{'user': 'asdw', 'pwd': 'asdw131'}、{'user': 'oldboy', 'pwd': '123'}。

 五、用vuex實如今各個組件中共享值

(1)全局變量配置 

  1)建立/src/store文件夾,建立並編寫store.js文件:

import Vue from 'vue'
import Vuex from 'vuex'
// import Cookie from 'vue-cookies'

Vue.use(Vuex)

export default new Vuex.Store({
    // 組件中經過 this.$store.state.username 調用
    state: {
        username: null,
        token: null,
    },
})

  組件中經過 this.$store.state.username 調用。

  2)在main.js中引入store,並放入實例化組件中

import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store/store'

// 在vue的全局變量中設置了 $axios=axios
// 之後每一個組件使用時:this.$axios
Vue.prototype.$axios = axios;

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,   // 放入實例化中
    components: {App},
    template: '<App/>'
})

(2)在全部組件中使用全局變量

  Login.vue:

<script>
    export default {
        data(){
            return {
                // 經過v-model雙向綁定用戶名和密碼
                username:'',
                password:''
            }
        },
        methods: {
            doLogin(){
                var that = this;
                this.$axios.request({
                    url:'http://127.0.0.1:8000/api/v1/auth/',
                    method:'POST',
                    data:{
                        user:this.username,
                        pwd:this.password
                    },
                    headers:{
                        'Content-Type': 'application/json'
                    }
                }).then(function (arg) {
                    // 拿回結果
                    if (arg.data.code === 1000){
                        // 成功的狀況下
                        that.$store.state.token = arg.data.token;
                        that.$store.state.username = that.username;

                    }else {
                        alert(arg.data.error)
                    }
                }).catch(function (arg) {
                    // 拿到錯誤信息
                    console.log("發生錯誤")
                })
            }
        }
    }
</script>

  App.vue:

<template>
    <div id="app">

        <router-link to="/index">首頁</router-link>
        <router-link to="/course">課程</router-link>
        <router-link to="/micro">微職位</router-link>
        <router-link to="/news">深科技</router-link>
        <div v-if="this.$store.state.token">
            <a href="">{{this.$store.state.username}}</a>
        </div>
        <div v-else>
            <router-link to="/login">登陸</router-link>
        </div>
        <router-view/>
    </div>
</template>

<script>
    export default {
        name: 'App'
    }
</script>

  如此就能夠經過獲取全局變量實現用戶登陸效果:

  

  可是這種登陸狀態,只要瀏覽器一刷新,登陸狀態就消失了,所以登陸成功不只要設置到全局變量,還要在cookie中放一份全局變量。

 六、vue-cookies應用

(1)store.js

import Vue from 'vue'
import Vuex from 'vuex'
import Cookie from 'vue-cookies'  // 引入cookie,npm install vue-cookies --save

Vue.use(Vuex);

export default new Vuex.Store({
    // 組件中經過 this.$store.state.username 調用
    state: {
        // 默認去cookie中取值
        username: Cookie.get("username"),
        token: Cookie.get("token"),
    },
    mutations: {
        // 組件中經過this.$store.commit(函數名, 參數)調用
        saveToken: function (state, userToken) {
            state.username = userToken.username;
            state.token = userToken.token;
            Cookie.set("username", userToken.username, "20min");
            Cookie.set("token", userToken.token, "20min");
        },
    }
})

  1)注意引入cookie的方法;

  2)注意mutations方法。更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。

  3)組件中經過this.$store.commit(函數名, 參數)調用。

(2)Login.vue修改

<script>
    export default {
        data(){
            return {
                // 經過v-model雙向綁定用戶名和密碼
                username:'',
                password:''
            }
        },
        methods: {
            doLogin(){
                var that = this;
                this.$axios.request({
                    url:'http://127.0.0.1:8000/api/v1/auth/',
                    method:'POST',
                    data:{
                        user:this.username,
                        pwd:this.password
                    },
                    headers:{
                        'Content-Type': 'application/json'
                    }
                }).then(function (arg) {
                    // 拿回結果
                    if (arg.data.code === 1000){
                        // 成功的狀況下
                        // that.$store.state.token = arg.data.token;
                        // that.$store.state.username = that.username;
                        that.$store.commit('saveToken',{token: arg.data.token, username: that.username});
                    }else {
                        alert(arg.data.error)
                    }
                }).catch(function (arg) {
                    // 拿到錯誤信息
                    console.log("發生錯誤")
                })
            }
        }
    }
</script>

(3)刷新仍在全局顯示登陸用戶

  

(4)添加登出註銷操做

  App.vue:

<template>
    <div id="app">

        <router-link to="/index">首頁</router-link>
        <router-link to="/course">課程</router-link>
        <router-link to="/micro">微職位</router-link>
        <router-link to="/news">深科技</router-link>
        <div v-if="this.$store.state.token">
            <a href="">{{this.$store.state.username}}</a>
            <a @click="logout">註銷</a>
        </div>
        <div v-else>
            <router-link to="/login">登陸</router-link>
        </div>
        <router-view/>
    </div>
</template>

<script>
    export default {
        name: 'App',
        methods:{
            logout(){   // 註銷
                this.$store.commit('clearToken');
            }
        }
    }
</script>

  store.js:

import Vue from 'vue'
import Vuex from 'vuex'
import Cookie from 'vue-cookies'  // 引入cookie,npm install vue-cookies --save

Vue.use(Vuex);

export default new Vuex.Store({
    // 組件中經過 this.$store.state.username 調用
    state: {
        // 默認去cookie中取值
        username: Cookie.get("username"),
        token: Cookie.get("token"),
    },
    mutations: {
        // 組件中經過this.$store.commit(函數名, 參數)調用
        saveToken: function (state, userToken) {
            state.username = userToken.username;
            state.token = userToken.token;
            Cookie.set("username", userToken.username, "20min");
            Cookie.set("token", userToken.token, "20min");
        },
        clearToken: function (state) {
            state.username = null;
            state.token = null;
            Cookie.remove("username");
            Cookie.remove("token");
        }
    }
})

  登出效果以下所示:

  

  點擊註銷後顯示效果:

  

4、攔截器 

  有些頁面登陸了才能訪問,有些頁面不須要登陸便可訪問。

一、頁面訪問登陸判斷

  這裏以micro模塊爲例,給模塊添加登陸判斷,用戶未登陸時訪問微職業,直接跳轉到登陸頁面。

<template>
    <div>
        <h1>LuffyX學位</h1>
    </div>
</template>

<script>
    export default {
        name: "index",
        data() {
            return {

            }
        },
        mounted(){   // 剛加載即執行
            if(!this.$store.state.token){
                // 重定向返回登陸頁面
                this.$router.push({name:"login"})
            }
        }
    }
</script>

<style scoped>

</style>

  可是對於組件不少的網站卻不能這麼處理,而是應該使用vue自帶的攔截器來處理。

二、添加攔截器

(1)在路由控制中給須要攔截的路由配置meta字段

  index.js:給須要攔截的路由配置meta字段

export default new Router({
    routes: [
        {
            path: '/index',
            name: 'index',
            component: Index,
        },
        {
            path: '/course',
            name: 'course',
            component: Course
        },
        {
            path: '/detail/:id',   // 動態接收名字爲id的值
            name: 'detail',
            component: Detail
        },
        {
            path: '/micro',
            name: 'micro',
            component: Micro,
            meta:{
                requireAuth:true    // 表示必需要登陸
            }
        },
        {
            path: '/news',
            name: 'news',
            component: News,
            meta:{
                requireAuth:true    // 表示必需要登陸
            }
        },
        {
            path: '/login',
            name: 'login',
            component: Login
        },
    ],
    mode: 'history'
})

(2)添加配置攔截器

  main.js:

import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store/store'

// 在vue的全局變量中設置了 $axios=axios
// 之後每一個組件使用時:this.$axios
Vue.prototype.$axios = axios;

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,   // 放入實例化中
    components: {App},
    template: '<App/>'
});

// 攔截器  to:要去哪  next:去跳轉  from:從哪來
router.beforeEach(function (to, from, next) {
    if (to.meta.requireAuth) {
        // 當前要去的url只有登陸後才能訪問
        if (store.state.token) {
            // token爲true表示能夠繼續訪問
            next()
        } else {
            // token不爲true跳轉到登陸頁面
            next({path:'/login',})
        }
    } else {
        // url不須要訪問便可以訪問
        next()
    }
});

三、登陸後直接顯示登陸前頁面

  好比在訪問微職業時,因爲沒有登陸跳轉到了登陸頁面,輸入帳戶密碼登陸後,顯示的內容應該是微職業的內容。

(1)修改main.js中的攔截器

  在url地址中添加返回的url:

// 攔截器  to:要去哪  next:去跳轉  from:從哪來
router.beforeEach(function (to, from, next) {
    if (to.meta.requireAuth) {
        // 當前要去的url只有登陸後才能訪問
        if (store.state.token) {
            // token爲true表示能夠繼續訪問
            next()
        } else {
            // token不爲true跳轉到登陸頁面
            next({path:'/login', query:{backUrl: to.fullPath}})
        }
    } else {
        // url不須要訪問便可以訪問
        next()
    }
});

(2)Login.vue中修改登陸操做

<script>
    export default {
        data(){
            return {
                // 經過v-model雙向綁定用戶名和密碼
                username:'',
                password:''
            }
        },
        methods: {
            doLogin(){
                var that = this;
                this.$axios.request({
                    url:'http://127.0.0.1:8000/api/v1/auth/',
                    method:'POST',
                    data:{
                        user:this.username,
                        pwd:this.password
                    },
                    headers:{
                        'Content-Type': 'application/json'
                    }
                }).then(function (arg) {
                    // 拿回結果
                    if (arg.data.code === 1000){
                        // 成功的狀況下
                        that.$store.commit('saveToken',{token: arg.data.token, username: that.username});
                        var url = that.$route.query.backUrl;
                        if (url) {
                            that.$router.push({path:url})
                        } else {
                            that.$router.push({path:'/index'})
                        }
                    }else {
                        alert(arg.data.error)
                    }
                }).catch(function (arg) {
                    // 拿到錯誤信息
                    console.log("發生錯誤")
                })
            }
        }
    }
</script>

(3)登陸驗證

  

  登陸成功後顯示效果:

  

5、用戶認證

一、經過token進行用戶認證

(1)配置micro的url和視圖

  api/urls.py:

urlpatterns = [
    """省略"""
    url(r'^(?P<version>[v1|v2]+)/micro/$', course.MicroView.as_view()),
]

  Couse.py添加MicroView視圖:

class MicroView(APIView):

    def get(self, request, *args, **kwargs):
        token = request.query_params.get('token')   # 獲取到token
        obj = models.UserToken.objects.filter(token=token)   # 與數據庫中token檢驗
        if not obj:
            return Response("認證失敗")
        return Response("微職位")

(2)配置Micro.vue向後端發送GET請求

<script>
    export default {
        name: "index",
        data() {
            return {
                title:null
            }
        },
        mounted(){   // 剛加載即執行
            this.initMicro()
        },
        methods:{
            initMicro(){
                this.$axios.request({
                    url:'http://127.0.0.1:8000/api/v1/micro/',  // 這個地址若是被盜,任何人均可以獲取數據
                    method:"GET",
                    params:{
                        token:this.$store.state.token
                    }
                }).then(function (arg) {
                    console.log(arg);
                })
            }
        }
    }
</script>

  這裏須要注意不能只配置Url,這個地址若是被盜,則任何人均可以向後端發送請求獲取數據。

  所以配置params參數,在url地址後拼接token參數來發送請求:

  

(3)django訪問檢驗

  

  當token不正確時:

  

二、經過rest認證組件實現用戶認證

(1) 在應用api下添加文件夾auth,添加auth.py文件

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from api import models

class LuffyAuth(BaseAuthentication):

    def authenticate(self, request):
        token = request.query_params.get("token")
        obj = models.UserToken.objects.filter(token=token).first()
        if not obj:
            raise AuthenticationFailed({"code":1001, "error": "認證失敗"})
        return (obj.user.user, obj)   # 返回用戶名和token對象

(2)在MicroVIew視圖類中添加認證組件 

from api.auth.auth import LuffyAuth

class MicroView(APIView):

    authentication_classes = [LuffyAuth]

    def get(self, request, *args, **kwargs):
        ret = {"code":1000, "title":"微職位"}
        return Response(ret)

  訪問django頁面驗證:

  

(3)前端vue處理後端返回的數據

<template>
    <div>
        <h1>LuffyX學位:{{title}}</h1>
    </div>
</template>

<script>
    export default {
        name: "index",
        data() {
            return {
                title:null
            }
        },
        mounted(){   // 剛加載即執行
            this.initMicro()
        },
        methods:{
            initMicro(){
                var that = this;
                this.$axios.request({
                    url:'http://127.0.0.1:8000/api/v1/micro/',  // 這個地址若是被盜,任何人均可以獲取數據
                    method:"GET",
                    params:{
                        token:this.$store.state.token
                    }
                }).then(function (arg) {
                    if (arg.data.code === 1000) {
                        that.title = arg.data.title
                    }
                })
            }
        }
    }
</script>

  訪問http://localhost:8080/micro,效果以下所示:

  

6、vue接口歸總

一、在vuex中設置apiList字段歸總全部rest接口

import Vue from 'vue'
import Vuex from 'vuex'
import Cookie from 'vue-cookies'  // 引入cookie,npm install vue-cookies --save

Vue.use(Vuex);

export default new Vuex.Store({
    // 組件中經過 this.$store.state.username 調用
    state: {
        // 默認去cookie中取值
        username: Cookie.get("username"),
        token: Cookie.get("token"),
        apiList: {
            // 全部的接口
            course: 'http://127.0.0.1:8000/api/v1/course/',
            courseDetail: 'http://127.0.0.1:8000/api/v1/course/',
            auth: 'http://127.0.0.1:8000/api/v1/auth/',
            micro: "http://127.0.0.1:8000/api/v1/micro/",
        }
    },
    mutations: {
        /* 代碼省略*/
    }
})

二、替換各個模塊中的url地址

  均按照以下方法替換:

url: this.store.state.apiList.micro,
url: this.store.state.apiList.course,
url: this.store.state.apiList.course + nid + '/',
url: this.store.state.apiList.auth,
相關文章
相關標籤/搜索