学习网站项目学习 - Django & Vue - 后台进行过滤操作,前端实现课程类别分页

目录

一、实现思路总结

1-1 实现样式

1-2 前端发送分页数据和课程请求

1-3 后台路由接收,执行视图函数

1-4 序列化组件校验规则

1-5 通用状态类

1-6 返回前端的数据查询

 1-7 前端获取数据并渲染页面

二、前端代码

三、表结构设计


一、实现思路总结

1-1 实现样式

1-2 前端发送分页数据和课程请求

1-3 后台路由接收,执行视图函数

class Course(ViewSetMixin, APIView):

    def get_list(self, request, *args, **kwargs):
        '''
        页面加载发送请求,后台首先执行的视图函数
            - response返回执行状态
            从get中获取sub_category内,即前端返回的数据。
            若返回的数据不为空,则进入数据库进行校验,过滤出对象。
            过滤出的对象使用DRF的序列化组件,并将其放在response内返回前台
        '''
        # 实例化MyResponse,即生成结束字典
        response = MyResponse()

        course_list = models.Course.objects.all()
        # 实现过滤查询,sub_category为前端传输数据名
        param = request.GET.get('sub_category', None)

        # 前端接受数据为字符串'0'则不为空
        param = int(param)
        if param:
            course_list = course_list.filter(category_id=param)
        course_ser = MySerializers.CourseSerializer(instance=course_list, many=True)

        # 获取课程类别,加入response对象内,返回前端
        category_list = models.CourseCategory.objects.all()
        category_ser = MySerializers.CourseCategorySerializer(instance=category_list, many=True)

        response.msg = '查询成功'
        response.data = course_ser.data
        response.category = category_ser.data

        return Response(response.get_dic)

1-4 序列化组件校验规则

from rest_framework import serializers
from LearnOnline import models


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


class CourseCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.CourseCategory
        fields = '__all__'

1-5 通用状态类

class MyResponse():
    '''
    通用的返回类,实例化后可以将内部的属性变成字典形式传输;
    即,{status='100',msg=None}
    使用get_dic方法可以获取字典
    '''
    def __init__(self):
        self.status = 100
        self.msg = None

    @property
    def get_dic(self):
        return self.__dict__

1-6 返回前端的数据查询

 1-7 前端获取数据并渲染页面

二、前端代码

 

<template>
    <div class="course">
        <h3>免费课程展示页</h3>
        <el-tabs v-model="activeName" @tab-click="handleClick">
            <el-tab-pane v-for="courcategory in course_category">
                <!--<span slot="label" @click="init(courcategory.id)"> {{courcategory.name}}</span>-->
                <span slot="label" @click="init(courcategory.nid)"> {{courcategory.name}}</span>
                <el-row>
                    <el-col :span="8" v-for="course in courses">
                        <el-card :body-style="{ padding: '0px' }">
                            <img :src="course.course_img" class="image">
                            <div style="padding: 14px;">
                                <span>{{course.name}}</span>
                                <div class="bottom clearfix">
                                    <el-button type="text" class="button">
                                        <!--跳转路由courseDetail,携带参数params,注意params key名不可变-->
                                        <router-link :to="{'name':'courseDetail','params':{'id':course.id}}">详情
                                        </router-link>
                                        <!--<router-link to="/courseDetail">课程详情</router-link>-->
                                    </el-button>
                                </div>

                            </div>
                        </el-card>
                    </el-col>
                </el-row>
            </el-tab-pane>

        </el-tabs>


    </div>

</template>

<style>
    .time {
        font-size: 13px;
        color: #999;
    }

    .bottom {
        margin-top: 13px;
        line-height: 12px;
    }

    .button {
        padding: 0;
        float: right;
    }

    .image {
        width: 100%;
        display: block;
    }

    .clearfix:before,
    .clearfix:after {
        display: table;
        content: "";
    }

    .clearfix:after {
        clear: both
    }

</style>

<script>
    export default {
        data: function () {
            return {
                courses: [],
                currentDate: new Date(),
                //默认前台分类数据,可以通过后台传输
                // course_category: [{'id': '0', 'name': '全部'},{'id': '1', 'name': 'python'}, {'id': '2', 'name': 'java'}, {
                //     'id': '3',
                //     'name': 'C语言'
                // }],
                course_category: [],
            };
        },
        methods: {
            init: function (category = 0) {
                let _this = this
                this.$http.request({
                    url: _this.$url + 'course/' + '?sub_category=' + category,
                    method: 'get'
                }).then(function (response) {
                    console.log(response.data);
                    _this.courses = response.data.data;
                    _this.course_category = response.data.category;

                }).catch(function (response) {
                    console.log(response)
                })

            }
        },
        mounted: function () {
            this.init()

        }
    }
</script>

三、表结构设计

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.fields import GenericRelation


# ------------课程相关--------------------

class Course(models.Model):
    '''
    免费课程
        - name :课程名称,唯一操作
        - course_img:课程图片
        - brief:课程概述,verbose_name在后台中文显示
        - level:课程等级
        - pub_date:发布时间,blank后台可不填
        - period:课程建议周期,后台中文显示
        - order:课程顺序(可以不要)
        - status:课程状态
        - category:课程类别,与课程类别表进行外键关联,实现choices功能方便扩展
        - price_policy:课程的价格策略,与PricePolicy表进行关联,不生成字段,仅用于反向查询
            - GenericRelation("PricePolicy") 注意默认参数 object_id_field='object_id', content_type_field='content_type'
    '''
    name = models.CharField(max_length=128, unique=True)
    course_img = models.CharField(max_length=255)
    brief = models.TextField(verbose_name="课程概述", max_length=2048)
    level_choices = ((0, '初级'), (1, '中级'), (2, '高级'))
    level = models.SmallIntegerField(choices=level_choices, default=1)
    pub_date = models.DateField(verbose_name="发布日期", blank=True, null=True)
    period = models.PositiveIntegerField(verbose_name="建议学习周期(days)", default=7)
    order = models.IntegerField("课程顺序", help_text="从上一个课程数字往后排")
    status_choices = ((0, '上线'), (1, '下线'), (2, '预上线'))
    status = models.SmallIntegerField(choices=status_choices, default=0)

    # category_choices = ((0, 'go'), (1, 'Python'), (2, 'Linux'))
    # category = models.SmallIntegerField(choices=category_choices, default=1)
    category = models.ForeignKey(to='CourseCategory', to_field='nid', null=True)

    price_policy = GenericRelation("PricePolicy")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "专题课"


class CourseCategory(models.Model):
    '''
    实现与Course表的类别对应,实现choices类似功能,但是方便拓展
        - nid :类别id自增
        - name:类别名字
    '''
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name


class CourseDetail(models.Model):
    '''
    课程详细信息表
        - course:与课程表进行一对一关联,on_delete设置当删除时,两个同时删除
        - hours:课程时长,位置传参verbose_name后台显示中文
        - course_slogan:课程的标语、口号、简单信息,后台允许为空
        - recommend_courses:推荐课程,例如A课页面可通过推荐进入B课;
            - 与课程表进行多对多关联
            - related_name基于对象的反向查询,代替表名小写_set
        - teachers:授课老师,与老师表进行多对多关系
    '''
    course = models.OneToOneField("Course", on_delete=models.CASCADE)
    hours = models.IntegerField("课时")
    course_slogan = models.CharField(max_length=125, blank=True, null=True)
    # video_brief_link = models.CharField(verbose_name='课程介绍', max_length=255, blank=True, null=True)
    # why_study = models.TextField(verbose_name="为什么学习这门课程")
    # what_to_study_brief = models.TextField(verbose_name="我将学到哪些内容")
    # career_improvement = models.TextField(verbose_name="此项目如何有助于我的职业生涯")
    # prerequisite = models.TextField(verbose_name="课程先修要求", max_length=1024)

    recommend_courses = models.ManyToManyField("Course", related_name="recommend_by", blank=True)
    teachers = models.ManyToManyField("Teacher", verbose_name="课程讲师")

    def __str__(self):
        return "%s" % self.course

    class Meta:
        verbose_name_plural = "课程详细"


class Teacher(models.Model):
    '''
    老师表
        - name:老师姓名
        - image:老师宣传图片
        - brief:老师介绍信息
    '''
    name = models.CharField(max_length=32)
    image = models.CharField(max_length=128)
    brief = models.TextField(max_length=1024)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = "讲师"


class PricePolicy(models.Model):
    '''
    价格策略表
        - ContentType组件相关
            - content_type:外键ContentType表,设置删除记录二者同时删除
            - object_id
            - content_object:用于数据的查询和插入
        - valid_period:周期兑换
        - price:课程价格
        - Meta相关
            - unique_together三者进行联合唯一,即,一个课程id只能允许一个时间周期
            - verbose_name_plural 后台显示中文
    '''
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    # 可建立第三张表使用外键实现 course = models.ForeignKey("Course")
    valid_period_choices = ((1, '1天'), (3, '3天'),
                            (7, '1周'), (14, '2周'),
                            (30, '1个月'),
                            (60, '2个月'),
                            (90, '3个月'),
                            (180, '6个月'), (210, '12个月'),
                            (540, '18个月'), (720, '24个月'),
                            )
    valid_period = models.SmallIntegerField(choices=valid_period_choices)
    price = models.FloatField()

    class Meta:
        unique_together = ("content_type", 'object_id', "valid_period")
        verbose_name_plural = "价格策略"

    def __str__(self):
        return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price)

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/85252401