Vue向后端請求課程展示


1.Vue結構

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>
    <router-view/>
  </div>
</template>

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

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  color: #2c3e50;
}
</style>

這里進行利路由設置,那么需要在index中進行掛載

import Vue from 'vue'
import Router from 'vue-router'
// 導入模塊
import Index from '../components/Index'    
import Course from '../components/Course'
import Micro from '../components/Micro'
import News from '../components/News'
import Detail from '../components/Detail'

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/index',
      name: 'index',
      component: Index
    },
    {
      path: '/course',
      name: 'course',
      component: Course
    },
    {
      path: '/detail/:id',
      name: 'detail',
      component: Detail
    },

    {
      path: '/micro',
      name: 'micro',
      component: Micro
    },{
      path: '/news',
      name: 'news',
      component: News
    }

  ],
  mode:'history'    //取出url里面的#號
})

在main.js中導入axios,和ajax一樣。

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


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

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})
View Code

在課程中向后端發送請求並用v-for進行展示

<template>
  <div>
  <h1>課程列表</h1>
  <ul v-for="row in courseList">
      <li><router-link :to="{name:'detail',params:{id:row.id}}">{{row.title}}</router-link></li>
    //這里利用:to來傳入一個課程的ID,這樣可以知道點擊哪個課程的詳細頁。 </ul> </div> </template> <script> export default { name: "course", data(){ return { msg:"課程", courseList:[ ] } }, mounted:function () { //vue頁面剛加載時執行 this.initCourse() }, methods:{ initCourse:function () { //去通過ajax向接口發送請求並獲取課程列表數據 //axios/jquery //第一步在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){ that.courseList=ret.data.data } }).catch(function(ret){ //上面發生異常執行這個 }) } } } </script> <style scoped> </style>

這邊設置好后,在Detail.vue中

<template>
    <h1>課程詳細頁面</h1>
</template>

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

          }
      },
      mounted(){
          console.log(this);  #Vue對象
          console.log(this.$route.params.id)   #通過這個可以拿到這個ID,
      }
    }
</script>

<style scoped>

</style>

 這里的數據是假數據,所以應該真正的去后端創建數據表,並且編寫API接口

1.創建models表

from django.db import models

# Create your models here.
class Course(models.Model):
    '''
    課程表
    '''
    title=models.CharField(max_length=32,verbose_name="課程名稱")
    course_img = models.CharField(max_length=64,verbose_name="課程圖片")
    level_choices=(
        (1,'初級'),
        (2,'中級'),
        (3,'高級'),
    )
    level=models.IntegerField(verbose_name="課程難易",choices=level_choices,default=1)
    def __str__(self):
        return self.title


class CourseDetail(models.Model):
    '''
    課程詳細
    '''
    course = models.OneToOneField(to="Course", on_delete=models.CASCADE)
    slogon=models.CharField(max_length=255,verbose_name="口號")
    why=models.CharField(max_length=255,verbose_name="為什么要學")
    recommend_courses=models.ManyToManyField(to="Course",verbose_name="推薦課程",related_name='rc')
    def __str__(self):
        return "課程詳細"+self.course.title


class Chapter(models.Model):
    '''
    章節表
    '''
    num=models.IntegerField(verbose_name="第幾章")
    name=models.CharField(max_length=32,verbose_name="章節名稱")
    coursedetail=models.ForeignKey("Course",on_delete=models.CASCADE,verbose_name="所屬課程")

    def __str__(self):
        return self.name
View Code

2.做一個序列化,並返回數據

from rest_framework.views import APIView
from rest_framework.response import Response
from api import models
from rest_framework import serializers


class CourseSerializer(serializers.ModelSerializer):
    class Meta:
        model=models.Course
        fields="__all__"    

from rest_framework.viewsets import GenericViewSet,ViewSetMixin
class CourseView(ViewSetMixin,APIView):
    def list(self,request,*args,**kwargs):
        '''
        課程列表接口
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        ret = {'code': 1000, "data": None}
        try:
            query=models.Course.objects.all()
            ser = CourseSerializer(instance=query,many=True)
            ret["data"]=ser.data
        except Exception as e:
            ret["code"]=1001
            ret["error"]="獲取課程失敗"
        return Response(ret)

    def retrieve(self,request,*args,**kwargs):
        '''
        課程詳細的接口
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        ret = {'code': 1000, "data": None}
        try:
            pk=kwargs.get('pk')
            obj = models.Course.objects.filter(id=pk).first()
            ser = CourseSerializer(instance=obj,many=False)
            ret["data"] = ser.data
        except Exception as e:
            ret["code"]=1001
            ret["error"]="獲取課程失敗"
        return Response(ret)    

3.因為后面的url使用了get不同需求的狀態,所以是重寫了as_view(),所以類中繼承的是

ViewSetMixin,zhe這樣的話,就可以對都是get請求使用同一個類,做出不同的響應,有PK的使用retrieve方法,沒有的使用list方法。
urlpatterns = [
    # url(r'^course/$', course.CourseView.as_view()),
    # url(r'^course/(?P<pk>\d+)/$', course.CourseView.as_view()),

    #這種方案必須繼承ViewSetMixin,它重寫了as_view,可以往里添加參數
    url(r'^course/$', course.CourseView.as_view({"get":"list"})),
    url(r'^course/(?P<pk>\d+)/$', course.CourseView.as_view({"get":"retrieve"})),

]        

最后是API接口

1.查詢所有課程:
http://127.0.0.1:8000/api/v1/course/
2.查詢單個課程:
http://127.0.0.1:8000/api/v1/course/1/

 但是因為有了新的需求,所以需要重新的來進行更多的定制。

from rest_framework.views import APIView
from rest_framework.response import Response
from api import models
from rest_framework import serializers


class CourseSerializer(serializers.ModelSerializer):
    class Meta:
        model=models.Course
        fields="__all__"


class CourseDetailSerializer(serializers.ModelSerializer):
    #o2o fk,choice
    title=serializers.CharField(source='course.title')      #只能這里通過跨表拿到以后,在下面展示 
    img=serializers.CharField(source='course.course_img')  
    level=serializers.CharField(source='course.get_level_display')  #通過get_level_display方法拿到choice對應的值,如果是方法需要加(),這里反射所以不加
    #m2m
    recommends = serializers.SerializerMethodField()     #這個因為是多對多字段,所以需要通過一個方法來拿到

    class Meta:
        model=models.CourseDetail
        fields=['course','title','recommends','level','img','slogon','why']  #想要展示的字段
        depth:1     #展示深度,這個就是說這個表如果有跟別的表跨表就會把那個表拿過來也序列化,深度越大,越往后關聯的越多。

    def get_recommends(self,obj):       #這里通過拿到這個queryset
        #獲取推薦的所有課程
        query=obj.recommend_courses.all()

        return [{'id':row.id,'title':row.title} for row in query]    #通過列表解析式將這個進行拆分成如下格式。



from rest_framework.viewsets import GenericViewSet,ViewSetMixin
class CourseView(ViewSetMixin,APIView):
    def list(self,request,*args,**kwargs):
        '''
        課程列表接口
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        ret = {'code': 1000, "data": None}
        try:
            query=models.Course.objects.all()
            ser = CourseSerializer(instance=query,many=True)
            ret["data"]=ser.data
        except Exception as e:
            ret["code"]=1001
            ret["error"]="獲取課程失敗"
        return Response(ret)

    def retrieve(self,request,*args,**kwargs):
        '''
        課程詳細的接口
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        ret = {'code': 1000, "data": None}
        try:
            pk=kwargs.get('pk')
            obj = models.CourseDetail.objects.filter(course_id=pk).first() #這里需要做的是這里會CourseDetail里面通過course_id跨表到course表
            ser = CourseDetailSerializer(instance=obj,many=False)    #這里使用了新的序列化類。
            ret["data"] = ser.data
        except Exception as e:
            ret["code"]=1001
            ret["error"]="獲取課程失敗"
        return Response(ret)

這里獲取具體每一個課程想要獲得更多的信息,而不是局限於那個課程表,所以建立了一個

CourseDetailSerializer的序列化類。


最終效果:

 最后做了一點優化以及解耦的分離:

# Author:Jesi
# Time : 2018/10/16 14:21
from rest_framework import serializers
from api import models


class CourseSerializer(serializers.ModelSerializer):
    '''
    課程序列化
    '''
    level=serializers.CharField(source='get_level_display')
    class Meta:
        model=models.Course
        fields='__all__'

class CourseDetailSerializer(serializers.ModelSerializer):
    '''
    課程詳細序列化
    '''

    #o2o fk,choice
    title=serializers.CharField(source='course.title')
    img=serializers.CharField(source='course.course_img')
    level=serializers.CharField(source='course.get_level_display')

    #m2m
    recommends = serializers.SerializerMethodField()
    chapter = serializers.SerializerMethodField()

    class Meta:
        model=models.CourseDetail
        fields=['course','title','recommends','level','chapter','img','slogon','why']
        depth:1

    def get_recommends(self,obj):
        #獲取推薦的所有課程
        query=obj.recommend_courses.all()
        return [{'id':row.id,'title':row.title} for row in query]

    def get_chapter(self,obj):
        #獲取推薦的章節
        query=obj.course.chapter_set.all()
        print(query)
        return [{'id':row.num,'name':row.name} for row in query]
View Code

 

在前端Vue里面對詳情頁進行了數據傳送:

<template>
  <div>
        <h1>課程詳細頁面</h1>
        <p>課程標題:{{detail.title}}</p>
        <p>圖片:{{detail.img}}</p>
        <p>課程難度:{{detail.level}}</p>
        <p>課程口號:{{detail.slogon}}</p>

        <p>為什么要學?{{detail.why}}</p>
        <div>
          章節:
          <ul v-for="item in detail.charter">
            <li>{{item.name}}</li>
          </ul>
        </div>

        <div>
          推薦課程:
          <ul v-for="item in detail.recommends">
            <li>{{item.title}}</li>
          </ul>
        </div>

  </div>

</template>

<script>
    export default {
        name: "detail",
      data(){
          return {
            detail:{
              charter:[],
              course:null,
              level:null,
              img:null,
              title:null,
              slogon:null,
              why:null,
              recommends:[]
            }

          }
      },
      mounted(){
          this.initDetail()
      },
      methods:{
        initDetail(){
          var nid=this.$route.params.id;
          var that = this;
          this.$axios.request({
              url:'http://127.0.0.1:8000/api/v1/course/'+nid+'/',
              method:"GET",

          }).then(function (arg) {
            if (arg.data.code ===1000){
               console.log(arg.data);
                that.detail=arg.data.data
            }else{
              alert(arg.data.error)
            }

          })
        }
    }
    }
</script>

<style scoped>

</style>
View Code

 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM