1. 程式人生 > >Django rest framework + Vue簡單示例

Django rest framework + Vue簡單示例

一、建立Vue專案

修改源:npm config set registry https://registry.npm.taobao.org         (建議修改)

建立腳手架:vue init webpack Vue專案名稱

基本外掛:

axios,傳送Ajax請求
vuex,儲存所有元件共用的變數
vue-cookies,操作cookie

二、流程

vue專案基本目錄結構

1.建立腳手架

vue init webpack Vue專案名稱

執行 npm run dev 

2.App.Vue中

# 用於點選檢視元件
<router-link to="/index">首頁</router-link> # 元件顯示的位置 <router-view/>

3.寫路由

寫在route/index.js中

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import index from '@/components/Index'
import Cource from 
'@/components/Cource' import Xw from '@/components/Xw' import Login from '@/components/Login' import CourseDetail from '@/components/CourseDetail' Vue.use(Router); export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld }, { path:
'/index', name: 'index', component: index }, { path: '/cource', name: 'Cource', component: Cource }, { path: '/xw', name: 'Xw', component: Xw }, { path: '/login', name: 'Login', component: Login }, { path: '/course-detail/:id/', name: 'CourseDetail', component: CourseDetail } ], mode: 'history' })
index.js

注意:

我們訪問的時候url一般會帶有‘#’,如果不想有,在路由後面加上  mode: 'history'

如果想url中想傳參:

 {
      path: '/course-detail/:id/',
      name: 'CourseDetail',
      component: CourseDetail
    }

4.寫元件

元件寫在src/components下

<template>
  <div class="hello">
   <h1>登入</h1>
    <input type="text"  v-model="username"><br>
    <input type="text"   v-model="password"><br>
    <a type="button" @click="doLogin">提交</a>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      username: '',
      password:'',
    }
  },
  methods:{
    doLogin(){
      var that = this;
      this.$axios.request({
        url:'http://127.0.0.1:8000/login/',
        method:'POST',
        data:{
          username:this.username,
          password:this.password
        },
        responseType:'json'
      }).then(function (response) {
        console.log(response.data);
        that.$store.commit('saveToken',response.data);
        // 重定向到index
        that.$router.push('/index')
      })

    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
View Code

5.類似與ajax的請求ajax請求:axios

下載:npm install axios

首先必須在main.js中匯入

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store/store'

Vue.prototype.$axios = axios;

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  components: { App },
  template: '<App/>'
});
main.js
import axios from 'axios'                
Vue.prototype.$axios = axios

使用:

複製程式碼
methods:{
    doLogin(){
      var that = this;
      this.$axios.request({
        url:'http://127.0.0.1:8000/login/',
        method:'POST',
        data:{
          username:this.username,
          password:this.password
        },
        responseType:'json'
      }).then(function (response) {
        console.log(response.data);
        that.$store.commit('saveToken',response.data);
        // 重定向到index
        that.$router.push('/index')
      })

    }
  }
複製程式碼

重定向: that.$router.push('/index')

6.vuex的使用

下載:npm install vuex 

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: Cookie.get('username'),
    token: Cookie.get('token')
  },
  mutations: {
    // 元件中通過 this.$store.commit(引數)  呼叫
    saveToken: function (state, data) {
      state.username = data.username;
      state.token = data.token;
      Cookie.set('username', data.username, '20min');
      Cookie.set('token', data.token, '20min')

    },
    clearToken: function (state) {
      state.username = null;
      state.token = null;
      Cookie.remove('username');
      Cookie.remove('token')
    }
  }
})
store.js

2.在main.js中匯入store

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store/store' //vuex

Vue.prototype.$axios = axios;

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,   //vuex
  router,
  components: { App },
  template: '<App/>'
});
main.js

7.vue-cookies 的使用

下載:npm install vue-cookies 

cookie的使用:

複製程式碼
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: Cookie.get('username'),
    token: Cookie.get('token')
  },
  mutations: {
    // 元件中通過 this.$store.commit(引數)  呼叫
    saveToken: function (state, data) {
      state.username = data.username;
      state.token = data.token;
      Cookie.set('username', data.username, '20min');
      Cookie.set('token', data.token, '20min')

    },
    clearToken: function (state) {
      state.username = null;
      state.token = null;
      Cookie.remove('username');
      Cookie.remove('token')
    }
  }
})
複製程式碼

8.router-link引數的常見用法

<router-link :to="{'path':'/course-detail/'+item.id }"{{item.name}}</router-link>
<router-link to="/index">首頁</router-link>

9. 獲取傳過來的引數

this.$route.params.id

10.重定向

this.$router.push('/index')

 

示例:

前端vue部分:

點選檢視元件

複製程式碼
<template>
  <div id="app">
    <router-link to="/index">首頁</router-link>
    <router-link to="/cource">課程</router-link>
    <router-link to="/xw">學位</router-link>
    <div>
          <div v-if="this.$store.state.username">
          <a>{{ this.$store.state.username }}</a>
          <a @click="logout">登出</a>
          </div>
          <router-link v-else to="/login">登入</router-link>
        </div>
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
  methods:{
    logout(){
      this.$store.state.username = '';
      this.$store.state.token = ''
    }
  }
}
</script>

<style>
/*#app {*/
  /*font-family: 'Avenir', Helvetica, Arial, sans-serif;*/
  /*-webkit-font-smoothing: antialiased;*/
  /*-moz-osx-font-smoothing: grayscale;*/
  /*text-align: center;*/
  /*color: #2c3e50;*/
  /*margin-top: 60px;*/
/*}*/
</style>
複製程式碼

元件

<template>
  <div class="hello">
   <h1>登入</h1>
    <input type="text"  v-model="username"><br>
    <input type="text"   v-model="password"><br>
    <a type="button" @click="doLogin">提交</a>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      username: '',
      password:'',
    }
  },
  methods:{
    doLogin(){
      var that = this;
      this.$axios.request({
        url:'http://127.0.0.1:8000/login/',
        method:'POST',
        data:{
          username:this.username,
          password:this.password
        },
        responseType:'json'
      }).then(function (response) {
        console.log(response.data);
        that.$store.commit('saveToken',response.data);
        // 重定向到index
        that.$router.push('/index')
      })

    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
Login.vue
<template>
  <div class="hello">
   <h1>首頁</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
index.vue
<template>
  <div class="hello">
       <ul>
      <li v-for="item in courseList" >
        <router-link :to="{'path':'/course-detail/'+item.id }">{{item.name}}</router-link>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      courseList: ''
    }
  },
  mounted:function () {
     this.initCourses()
  },
   methods: {
    initCourses:function () {
      var that = this;
      this.$axios.request({
        url: 'http://127.0.0.1:8000/courses/',
        method: 'GET'
      }).then(function (response) {
        that.courseList = response.data.courseList
      })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>
Cource.vue
<template>
  <div>
      <div>課程詳細</div>
      <h1>{{title}}</h1>
      <h1>{{summary}}</h1>

  </div>
</template>

<script>
export default {
  data () {
    return {
      title:'',
      summary:'',
    }
  },
  mounted:function () {
    this.initCourseDetail()
  },
  methods:{
    initCourseDetail (){
      var nid = this.$route.params.id;
      var that = this;
      var url = 'http://127.0.0.1:8000/courses/' + nid+'.json';
      this.$axios.request({
        url: url,
        method:'GET',
        responseType:'json'
      }).then(function (response) {
        console.log(response);
        that.title = response.data.title;
        that.summary = response.data.summary
      })
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>
CourceDetail.vue

路由:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import index from '@/components/Index'
import Cource from '@/components/Cource'
import Xw from '@/components/Xw'
import Login from '@/components/Login'
import CourseDetail from '@/components/CourseDetail'



Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/index',
      name: 'index',
      component: index
    },
    {
      path: '/cource',
      name: 'Cource',
      component: Cource
    },
    {
      path: '/xw',
      name: 'Xw',
      component: Xw
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
     {
      path: '/course-detail/:id/',
      name: 'CourseDetail',
      component: CourseDetail
    }
  ],
  mode: 'history'
})
index.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: Cookie.get('username'),
    token: Cookie.get('token')
  },
  mutations: {
    // 元件中通過 this.$store.commit(引數)  呼叫
    saveToken: function (state, data) {
      state.username = data.username;
      state.token = data.token;
      Cookie.set('username', data.username, '20min');
      Cookie.set('token', data.token, '20min')

    },
    clearToken: function (state) {
      state.username = null;
      state.token = null;
      Cookie.remove('username');
      Cookie.remove('token')
    }
  }
})
store.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import store from './store/store' //vuex

Vue.prototype.$axios = axios;

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,   //vuex
  router,
  components: { App },
  template: '<App/>'
});
main.js

 

後端restframwork部分

複製程式碼
"""luffyweb URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from api import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.LoginView.as_view()),
    url(r'^courses/$', views.CoursesView.as_view()),
    url(r'^courses/(?P<pk>\d+)\.(?P<format>[a-z0-9]+)$', views.CoursesView.as_view()),
]
複製程式碼 複製程式碼
from django.http import JsonResponse
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView

# Create your views here.

class LoginView(APIView):
    def get(self,request,*args,**kwargs):
        ret = {
            'code': 1000,
            'data': '老男孩'
        }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response

    def post(self,request,*args,**kwargs):

        print(request.POST)
        ret = {
            'code':1000,
            'username':'老男孩',
            'token':'71ksdf7913knaksdasd7',
        }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response

    def options(self, request, *args, **kwargs):
        # self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
        # self.set_header('Access-Control-Allow-Headers', "k1,k2")
        # self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
        # self.set_header('Access-Control-Max-Age', 10)

        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Headers'] = '*'
        #response['Access-Control-Allow-Methods'] = 'PUT'
        return response

class CoursesView(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        if pk:
            ret = {
                'title': "標題標題標題",
                'summary': '老師,太餓了。怎麼還不下課'
            }
        else:
            ret = {
                'code': 1000,
                'courseList': [
                    {"name": '21天學會Pytasdfhon', 'id': 1},
                    {"name": '23天學會Pytasdfhon', 'id': 2},
                    {"name": '24天學會Pytasdfhon', 'id': 3},
                ]
            }
        response = JsonResponse(ret)
        response['Access-Control-Allow-Origin'] = "*"
        return response
複製程式碼