1. 程式人生 > >學習網站專案學習 - Django & Vue - 後臺進行過濾操作,前端實現課程類別分頁

學習網站專案學習 - 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)