【Django+Vue3 线上教育平台项目实战】构建高效线上教育平台之首页模块
文章目录
- 前言
- 一、导航功能实现
- a.效果图:
- b.后端代码
- c.前端代码
- 二、轮播图功能实现
- a.效果图
- b.后端代码
- c.前端代码
- 三、标签栏功能实现
- a.效果图
- b.后端代码
- c.前端代码
- 四、侧边栏功能实现
- 1.整体效果图
- 2.侧边栏功能实现
- a.效果图
- b.后端代码
- c.前端代码
- 3.侧边栏展示分类及课程信息功能实现
- a.效果图
- b.后端代码
- c.前端代码
- 五、分类课程推荐(楼层设计)功能实现
- a.效果图
- b.后端代码
- c.前端代码
前言
在当今数字化教育浪潮中,构建一个高效且用户友好的线上教育平台至关重要。本博客将指导您使用Django作为后端框架,结合Vue 3的强大前端能力,快速搭建平台首页的核心功能,包括导航栏、轮播图、侧边栏、标签栏及分类课程推荐。我们将探讨前后端数据交互、Vue组件化开发等关键技术,轻松构建出既美观又实用的线上教育平台。
最终实现效果图如下:
一、导航功能实现
a.效果图:
b.后端代码
导航表模型类:
class NavigationModel(BaseModel): name = models.CharField(max_length=100) url = models.CharField(max_length=100) is_url = models.BooleanField(default=False) def __str__(self): return self.name class Meta: verbose_name = '导航表' verbose_name_plural = '导航表' db_table = 'navigation'
导航表序列化器:
class NavigationSerializer(serializers.ModelSerializer): class Meta: model = NavigationModel fields = ('id','name','url','is_url') # fields = '__all__'
获取所有头部导航栏信息:
class NavigationView(APIView): def get(self, request): nav_list = NavigationModel.objects.all() ser = NavigationSerializer(nav_list, many=True) return Response({"code":"200", "data":ser.data})
配置url信息:
urlpatterns = [ path('nav/header/', NavigationView.as_view()), ... ]
c.前端代码
components/Header.vue:
src/api/nav.js:
import http from "../http"; import {reactive} from "vue"; const nav = reactive({ header_nav_list: [], // 头部导航列表 get_header_nav(){ // 获取头部导航菜单 http.get("/home/nav/header/").then(response=>{ this.header_nav_list = response.data; }) }, }) export default nav;
二、轮播图功能实现
a.效果图
b.后端代码
轮播图模型类:
class BannerModel(BaseModel): image = models.CharField(max_length=255) link = models.CharField(max_length=255) is_http = models.BooleanField(default=False) def __str__(self): return self.image class Meta: verbose_name = "轮播图表" verbose_name_plural = "轮播图表" db_table = 'banner'
轮播图序列化器:
class BannerSerializer(serializers.ModelSerializer): class Meta: model = BannerModel fields = '__all__'
获取轮播图数据:
class BannerView(APIView): def get(self, request): banners = BannerModel.objects.all() ser = BannerSerializer(banners, many=True) return Response({"code":"200", "data":ser.data})
配置url信息:
path('banner/', BannerView.as_view()),
c.前端代码
src/components/Banner.vue:
import banner from "../api/banner"; banner.get_banner_list(); // 轮播图列表 接口数据替换 // http://192.168.56.1:3000/src/assets/img/course1.jpg const bannerImg = reactive([{ image: '/src/assets/img/course1.jpg', link: '', is_http: false, }]) // 当前轮播 banner背景 const nowBannerImg = reactive({ src: bannerImg[0].image }); //轮播切换赋值 const handleCarouselChange = (index) => { // 更新当前banner图片地址 nowBannerImg.src = banner.bannerImg[index].image; };
src/api/banner.js:
import { reactive } from "vue"; import http from "../http"; const banner = reactive({ bannerImg: [], // 轮播广告列表 get_banner_list() { // 获取轮播广告列表 return http.get("/home/banner/").then(response => { // console.log("Bannner---response.data"); // console.log(response.data); this.bannerImg = response.data.data; // console.log("bannerImg"); // console.log(response.data.data); }) }, }) export default banner;
三、标签栏功能实现
a.效果图
b.后端代码
标签表模型类:
class DirectionModel(BaseModel): direction = models.CharField(max_length=255) desc = models.CharField(max_length=255) icon = models.CharField(max_length=255) def __str__(self): return self.direction class Meta: verbose_name = "方向表" verbose_name_plural = "标签表" db_table = 'direction'
标签 / 方向表序列化器:
class DirectionSerializer(serializers.ModelSerializer): class Meta: model = DirectionModel fields = ['id','direction','desc','icon'] # fields = '__all__'
获取所有标签数据:
class DirectionView(APIView): def get(self, request): directions = DirectionModel.objects.all() ser = DirectionSerializer(directions, many=True) return Response({"code":"200", "data":ser.data})
配置urls:
path('directions/', DirectionView.as_view()),
c.前端代码
src/components/Banner.vue:
import directions from '../api/directions'; directions.get_directions_list();
src/api/directions.js:
import { reactive } from "vue"; import http from "../http"; const directions = reactive({ directions_list: [], // 标签列表 get_directions_list() { // 获取标签列表 return http.get("/home/directions/").then(response => { // console.log("11111111111111"); // console.log("directions_list---response.data"); // console.log(response.data); this.directions_list = response.data.data; // console.log(response.data.data); }) }, }) export default directions;
四、侧边栏功能实现
1.整体效果图
2.侧边栏功能实现
a.效果图
b.后端代码
分类表模型类:
class CategoryModel(BaseModel): id = models.AutoField(primary_key=True) # 通常Django会自动为主键添加AutoField,这里显式写出也可以 name = models.CharField(max_length=255, unique=True) # 假设分类名最大长度为255个字符 parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='son') # 自关联字段,表示父分类 recommend = models.BooleanField(default=False) def __str__(self): return self.name class Meta: verbose_name = '分类表' verbose_name_plural = '分类表' db_table = 'category'
父级分类序列化器、子级分类序列化器:
# 子类序列化器---二级分类 class SonCategorySerializer(serializers.ModelSerializer): class Meta: model = CategoryModel fields = ('id', 'name') # fields = '__all__' # 父类序列化器--一级分类 class CategorySerializer(serializers.ModelSerializer): son = SonCategorySerializer(many=True, read_only=True) class Meta: model = CategoryModel fields = '__all__' # fields = ('id','name','son')
获取父级与子级分类:
# 2.获取一、二级分类 class CategoryView(APIView): def get(self, request): # 查询所有一级分类:parent is null # query_set categories = CategoryModel.objects.filter(is_delete=0,parent__id__isnull=True) #query_set clist = [] #侧边栏 二级分类显示几个 for category in categories: # 获取一级下面所有的二级分类,操作显示二级分类数据条数 sondata = category.son.all()[0:2] #query_set # d对二级数据进行序列化操作 son = SonCategorySerializer(sondata, many=True) clist.append({"id": category.id, "name": category.name, "son": son.data}) return Response({"code":"200", "data":clist})
配置url:
path('nav/cates/', CategoryView.as_view()), #侧边栏-获取一二级分类
c.前端代码
src/components/Banner.vue:
import cates from "../api/cates"; cates.get_cates_list(); // 定义方法-展示侧边栏所有二级分类以及所有分类下的课程 const fnMethod = (cateid) => { state.current_menu = 0; cates.get_coures_list(cateid); };
src/api/cates.js:
import http from "../http"; import { reactive } from "vue"; const cates = reactive({ cates_list: [], // Banner---两级分类列表 get_cates_list() { // 获取两级分类 return http.get("/home/nav/cates/").then(response => { // console.log("左侧边栏获取两级分类response.data:"); // console.log(response.data); this.cates_list = response.data.data; }) }, }) export default cates;
3.侧边栏展示分类及课程信息功能实现
点击分类(侧边栏触发),获取此分类下所有的二级分类(@mouseover)以及此分类下推荐的课程
a.效果图
b.后端代码
+课程表模型类:
class CourseModel(BaseModel): id = models.AutoField(primary_key=True) name = models.CharField(max_length=255, unique=True) # parent 指向 Category 分类id parent = models.ForeignKey(CategoryModel, on_delete=models.CASCADE, related_name='course',verbose_name="parent-父级分类") topid = models.IntegerField(verbose_name="topid-顶级分类") recommend = models.BooleanField(default=False) picurl = models.CharField(max_length=100) price = models.FloatField() level = models.IntegerField(verbose_name="1零基础 2中级 3高级") sales = models.IntegerField(default=0,verbose_name="销量") describe = models.TextField() def __str__(self): return self.name class Meta: verbose_name = '课程表' verbose_name_plural = '课程表' db_table = 'course'
课程序列化器:
class CourseSerializer(serializers.ModelSerializer): # teacher = TeachersSerializer(many=True, read_only=True) # teacher = TeachersSerializer() class Meta: model = CourseModel fields = '__all__'
获取所有分类及其推荐课程:
class CategoryCourseView(APIView): def get(self, request): #获取一级分类id cateid = request.GET.get("cateid") #根据id查询分类:一级分类和二级分类 cate = CategoryModel.objects.filter(id=cateid).first() #通过id查询推荐课程 ser = CategorySerializer(cate) #返回结果 #print(cate.id) courses = CourseModel.objects.filter(topid=cateid,recommend=True) #print(courses) cSer = CourseSerializer(courses, many=True) #print(cSer.data) return Response({"code":"200", "clist":ser.data,"courses":cSer.data})
配置urls:
path('nav/catescourses/', CategoryCourseView.as_view()),#侧边栏-传一级分类id->展示子分类及其所有课程
c.前端代码
src/components/Banner.vue:
src/api/cates.js:
import http from "../http"; import { reactive } from "vue"; const cates = reactive({ cates_list: [], // Banner---两级分类列表 cc_list: {}, //Banner---触发显示:显示所有二级分类 course_list: [], //Banner ---触发显示:显示分类下的课程 get_cates_list() { // 获取两级分类 return http.get("/home/nav/cates/").then(response => { this.cates_list = response.data.data; }) }, get_coures_list(cateid) { // 获取所有二级分类 及其 课程 return http.get("/home/nav/catescourses/?cateid=" + cateid).then(response => { // console.log("左侧边栏获取课程分类及课程response.data:"); // console.log(response.data); this.cc_list = response.data.clist; this.course_list = response.data.courses; }) }, }) export default cates;
五、分类课程推荐(楼层设计)功能实现
首页分类课程推荐设计:
显示推荐分类,获取不同楼层不同分类下的课程,点击不同分类时获取当前楼层分类下的推荐课程并显示
a.效果图
b.后端代码
为了便于理解,建立三张表:频道表、频道分类表、频道课程表,模型类如下:
# a.频道表 class ChannelModel(BaseModel): name = models.CharField(max_length=255, unique=True) picurl = models.CharField(max_length=100) sort = models.IntegerField() def __str__(self): return self.name class Meta: verbose_name = '频道表' verbose_name_plural = '频道表' db_table = 'channel' # b.频道分类表 id,name,显示顺序,频道id,类别(1-添加的 2-分类的),分类id class ChannelCategoryModel(BaseModel): name = models.CharField(max_length=255) sort = models.IntegerField() channel = models.ForeignKey(ChannelModel, on_delete=models.CASCADE, related_name='cates') type = models.IntegerField() cateid = models.IntegerField() def __str__(self): return self.name class Meta: verbose_name = '频道分类表' verbose_name_plural = '频道分类表' db_table = 'channel_cates' # c.频道分类课程表 id,name,图标,价格,难度,购买人数,频道分类id class ChannelCoursesModel(BaseModel): name = models.CharField(max_length=255,unique=True) picurl = models.CharField(max_length=100) price = models.FloatField() sales = models.IntegerField(default=0) level = models.IntegerField() ccates = models.ForeignKey(ChannelCategoryModel, on_delete=models.CASCADE, related_name='courses') def __str__(self): return self.name class Meta: verbose_name = '频道分类课程表' verbose_name_plural = '频道分类课程表' db_table = 'channel_courses'
频道、频道分类、频道课程序列化器:
# -- # c.频道分类课程序列化器 class ChannelCourseSerializer(serializers.ModelSerializer): class Meta: model = ChannelCoursesModel fields = '__all__' # b.频道分类序列化器- class ChannelCategorySerializer(serializers.ModelSerializer): courses = ChannelCourseSerializer(many=True, read_only=True) class Meta: model = ChannelCategoryModel fields = '__all__' # a.频道序列化器 class ChannelSerializer(serializers.ModelSerializer): cates = ChannelCategorySerializer(many=True, read_only=True) class Meta: model = ChannelModel fields = '__all__'
获取首页推荐课程分类信息:
# 6.2 楼层-课程卡片--(无顺序版-->直接嵌套序列化器) class HomeCourseView(APIView): def get(self, request): channels = ChannelModel.objects.order_by('sort').all() ser_channels = ChannelSerializer(channels, many=True) return Response({"code":"200", "data":ser_channels.data})
配置urls:
path('homecourse/', HomeCourseView.as_view()), #首页推荐分类课程
c.前端代码
src/components/NewCourse.vue:
import {reactive} from "vue" // 接口取回的数据 import course from "../api/home"; course.get_courses_list(); // 定义每个频道TAB的下标 let courseList = reactive({data: [0,0,0]}) // 点击事件item-cates,key-二级index,index-一级index const selectTab = (item,key,index) => { courseList.data[index] = key state.current_menu[index] = key } const state = reactive({ current_menu: [0,0,0], })
src/api/home.js:
import { reactive } from "vue"; import http from "../http"; const course = reactive({ data: [], // 分类下课程信息 get_courses_list() { // 获取分类下课程信息 return http.get("/home/homecourse/").then(response => { console.log("response.data.data"); console.log(response.data.data); this.data = response.data.data; }, }) export default course;
{{c.name}} 体系