學習網站專案學習 - Django & Vue - 後臺進行過濾操作,前端實現課程類別分頁
阿新 • • 發佈:2018-12-29
目錄
一、實現思路總結
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)