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/>'
})
在课程中向后端发送请求并用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
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]
在前端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>
Vue向后端请求课程展示的更多相关文章
- vue中Axios请求豆瓣API数据并展示到Swipe中
vue中Axios请求豆瓣API数据并展示到Swipe中 1.首先是安装Axios: 安装方法cnpm install axios --save 等待npm安装完毕: 2.在main.js中引入axi ...
- ASP.NET WebApi+Vue前后端分离之允许启用跨域请求
前言: 这段时间接手了一个新需求,将一个ASP.NET MVC项目改成前后端分离项目.前端使用Vue,后端则是使用ASP.NET WebApi.在搭建完成前后端框架后,进行接口测试时发现了一个前后端分 ...
- Flask + vue 前后端分离的 二手书App
一个Flask + vue 前后端分离的 二手书App 效果展示: https://blog.csdn.net/qq_42239520/article/details/88534955 所用技术清单 ...
- SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题
原文链接:https://segmentfault.com/a/1190000012879279 当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异.笔者前几天刚好在负责一个项目的权限管理 ...
- 解决Django+Vue前后端分离的跨域问题及关闭csrf验证
前后端分离难免要接触到跨域问题,跨域的相关知识请参:跨域问题,解决之道 在Django和Vue前后端分离的时候也会遇到跨域的问题,因为刚刚接触Django还不太了解,今天花了好长的时间,查阅了 ...
- 喜大普奔,两个开源的 Spring Boot + Vue 前后端分离项目可以在线体验了
折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...
- 两个开源的 Spring Boot + Vue 前后端分离项目
折腾了一周的域名备案昨天终于搞定了. 松哥第一时间想到赶紧把微人事和 V 部落部署上去,我知道很多小伙伴已经等不及了. 1. 也曾经上过线 其实这两个项目当时刚做好的时候,我就把它们部署到服务器上了, ...
- beego-vue URL重定向(beego和vue前后端分离开发,beego承载vue前端分离页面部署)
具体过程就不说,是搞这个的自然会动,只把关键代码贴出来. beego和vue前后端分离开发,beego承载vue前端分离页面部署 // landv.cnblogs.com //没有授权转载我的内容,再 ...
- Vue获取后端数据 渲染页面后跳转
主页面 <template> <div> <ul v-for="item in courseList"> <router-link :to ...
随机推荐
- Linux学习历程——Centos 7重置root密码
一.自述 最近刚刚接触linux,因为我设置密码比较随性,把自己做系统的时候设置的root密码给forget,每当系统崩溃,重新把虚拟机备份还原后,就面临无法登陆的尴尬情况,只得重置root密码,好了 ...
- win7升级IE11后F12无法正常操作
今天在win7下把ie9升级为ie11,但是升级后发现ie11的F12无法正常操作,经过查找,发现需要安装win7补丁:KB3008923 下载地址:http://www.microsoft.com/ ...
- Windows Server2008 R2安装wampserver缺少api-ms-win-crt-runtime-l1-1-0.dll解决方案
安装wampserver经常会遇到缺少各种dll文件的问题,可以在安装之前先安装一下微软运行库合集,但此时仍有可能缺少api-ms-win-crt-runtime-l1-1-0.dll文件,那么可以尝 ...
- Qt在多线程中使用信号槽的示例
之前对线程理解得不深入,所以对Qt的线程机制没有搞清楚,今天写一篇文章总结一下,如有错误,欢迎指出. 首先需要理解线程是什么,线程在代码中的表现其实就是一个函数,只不过这个函数和主线程的函数同时运行, ...
- python——函数之装饰器
1 问题 实际生活中,我们很难一次性就把一个函数代码写得完美无缺.当我们需要对以前的函数添加新功能时,我们应该怎么做? 2 问题解决思路 (1)可以直接修改原来的函数,在函数内直接修改.当我们对多个函 ...
- gcc5.4报错对‘std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()’未定义的引用
我在编译ligra是遇到了这个问题,网上搜了一遍,发现是了原因https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/manual/using_dual_abi.ht ...
- LeetCode算法题-Reverse Linked List(Java实现)
这是悦乐书的第192次更新,第195篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第51题(顺位题号是206).反转单链表.例如: 输入:1-> 2-> 3- ...
- Linux 小知识翻译 - 「补丁」(patch)
这次,聊聊补丁. 当有bug或者安全漏洞的时候,就会发布补丁.打上补丁之后,就能解决相应的bug或者安全漏洞. 那么,「补丁」到底是什么呢? 「补丁」只有少量的代码,一般都是对程序的一部分进行更新或者 ...
- ABAP on HANA之CDS Association和Path Expression
本文阐述了ABAP CDS association的概念,并且展示了在CDS视图中和SQL语句中写路径表达式(Path Expression)代码的方法.我也会解释如何在CDS asociation中 ...
- DP 魔族密码 LIS
题目描述 风之子刚走进他的考场,就…… 花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花) 风之子:我呕……(杀死人的眼神)快说题目!否则……-_-### 花花:……咦好冷我们现在 ...