课程模块app应用、三大分页器、过滤组件
一、微信小程序
https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
1、创建course应用app
2、dev中注册course
3、路由
01、创建子路由
02、主路由:
path('course/', include('course.urls')),
4、models 表设计
分析:
免费课
实战课
轻课:
课程(免费课、实战课、轻课)与 表 的关系:
1、老师表,可以只有一张表,放在课件 基表中
2、分类表,可以只有一张表,放在课件 基表中
3、章节表,与课程 相对应,所以需要三张章节表,放在课程 子表中
4、课时表,与课程章节 相对应,所以需要三张章节表,放在课程 子表中
5、评论表 (外键自关联)
连表字段:
总时长:每个课程的每个章节的每个课时视频时间总和
(是估值,直接在课程表中写一个固定字段)
总人气:每个课程被学生学习的总量 (学习的人数),连表到user,查看课程与用户的关系记录总数(假值,直接在课程表中写一个固定字段)
总课时:每个课程的每个章节的总课时之和(确切值,直接在课程表中写一个固定字段,创建时算好算入)
数据库优化:大量查询的连表计算字段,可以直接用一个字段表示,能不连表尽量别连表
用uuid做主键,多个表之间主键不会重复
impord uuid
uuid.uuid4()
代码:

from django.db import models from utils.model import BaseModel class CourseCategory(BaseModel): """分类""" name = models.CharField(max_length=64, unique=True, verbose_name="分类名称") class Meta: db_table = "luffy_course_category" verbose_name = "分类" verbose_name_plural = verbose_name def __str__(self): return "%s" % self.name class Course(BaseModel): """课程""" course_type = ( (0, '付费'), (1, 'VIP专享'), (2, '学位课程') ) level_choices = ( (0, '初级'), (1, '中级'), (2, '高级'), ) status_choices = ( (0, '上线'), (1, '下线'), (2, '预上线'), ) name = models.CharField(max_length=128, verbose_name="课程名称") course_img = models.ImageField(upload_to="courses", max_length=255, verbose_name="封面图片", blank=True, null=True) course_type = models.SmallIntegerField(choices=course_type, default=0, verbose_name="付费类型") brief = models.TextField(max_length=2048, verbose_name="详情介绍", null=True, blank=True) level = models.SmallIntegerField(choices=level_choices, default=0, verbose_name="难度等级") pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True) attachment_path = models.FileField(upload_to="attachment", max_length=128, verbose_name="课件路径", blank=True, null=True) status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="课程状态") pub_sections = models.IntegerField(verbose_name="课时更新数量", default=0) price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价", default=0) students = models.IntegerField(verbose_name="学习人数", default=0) period = models.IntegerField(verbose_name="建议学习周期(day)", default=7) sections = models.IntegerField(verbose_name="总课时数量", default=0) teacher = models.ForeignKey("Teacher", on_delete=models.DO_NOTHING, null=True, blank=True, verbose_name="授课老师", db_constraint=False) course_category = models.ForeignKey("CourseCategory", on_delete=models.SET_NULL, null=True, blank=True, verbose_name="课程分类", db_constraint=False) @property def course_type_name(self): return self.get_course_type_display() @property def level_name(self): return self.get_level_display() @property def status_name(self): return self.get_status_display() # 连表序列化字段 @property def section_list(self): # 检索所以章节所以课时,返回前4课时,不足4课时全部返回 temp_section_list = [] for chapter in self.coursechapters.all(): for section in chapter.coursesections.all(): temp_section_list.append({ 'name': section.name, 'section_link': section.section_link, 'duration': section.duration, 'free_trail': section.free_trail, }) if len(temp_section_list) >= 4: return temp_section_list # 最多4条 return temp_section_list # 不足4条 class Meta: db_table = "luffy_course" verbose_name = "课程" verbose_name_plural = "课程" def __str__(self): return "%s" % self.name class Teacher(BaseModel): """导师""" role_choices = ( (0, '讲师'), (1, '导师'), (2, '班主任'), ) name = models.CharField(max_length=32, verbose_name="导师名") role = models.SmallIntegerField(choices=role_choices, default=0, verbose_name="导师身份") title = models.CharField(max_length=64, verbose_name="职位、职称") signature = models.CharField(max_length=255, verbose_name="导师签名", help_text="导师签名", blank=True, null=True) image = models.ImageField(upload_to="teacher", null=True, verbose_name="导师封面") brief = models.TextField(max_length=1024, verbose_name="导师描述") @property def role_name(self): return self.get_role_display() class Meta: db_table = "luffy_teacher" verbose_name = "导师" verbose_name_plural = verbose_name def __str__(self): return "%s" % self.name class CourseChapter(BaseModel): """章节""" course = models.ForeignKey("Course", related_name='coursechapters', on_delete=models.CASCADE, verbose_name="课程名称", db_constraint=False) chapter = models.SmallIntegerField(verbose_name="第几章", default=1) name = models.CharField(max_length=128, verbose_name="章节标题") summary = models.TextField(verbose_name="章节介绍", blank=True, null=True) pub_date = models.DateField(verbose_name="发布日期", auto_now_add=True) class Meta: db_table = "luffy_course_chapter" verbose_name = "章节" verbose_name_plural = verbose_name def __str__(self): try: return "%s:(第%s章)%s" % (self.course, self.chapter, self.name) except: return "(第%s章)%s" % (self.chapter, self.name) class CourseSection(BaseModel): """课时""" section_type_choices = ( (0, '文档'), (1, '练习'), (2, '视频') ) chapter = models.ForeignKey("CourseChapter", related_name='coursesections', on_delete=models.CASCADE, verbose_name="课程章节", db_constraint=False) name = models.CharField(max_length=128, verbose_name="课时标题") orders = models.PositiveSmallIntegerField(verbose_name="课时排序") section_type = models.SmallIntegerField(default=2, choices=section_type_choices, verbose_name="课时种类") section_link = models.CharField(max_length=255, blank=True, null=True, verbose_name="课时链接", help_text="若是video,填vid,若是文档,填link") duration = models.CharField(verbose_name="视频时长", blank=True, null=True, max_length=32) # 仅在前端展示使用 pub_date = models.DateTimeField(verbose_name="发布时间", auto_now_add=True) free_trail = models.BooleanField(verbose_name="是否可试看", default=False) class Meta: db_table = "luffy_course_Section" verbose_name = "课时" verbose_name_plural = verbose_name def __str__(self): # 在断关联情况下,可以先创课时,后创章节,但没有创章节时,查看课时就会报错(admin|xadmin) try: return "%s-%s" % (self.chapter, self.name) except: return self.name
5、admin管理 表类
6、数据库迁移命令:
python manage.py makemigrations
python manage.py migrate
7、navicat填充数据
8、前端:views中建文件:FreeCourse
9、写路由 router中 的index.js文件
10 、课程分类:群查接口
11、课程:群查接口
viesw文件
serializers文件
子序列化字段
自定义序列化字段
连表 序列化字段
urls文件
分页器组件:
paginate_queryset、filter_queryset 从GenericViewSet中的GenericAPIView中来的
点击GenericAPIView有如下:
from rest_framework.generic import GenericAPIView
GenericAPIView 的五个方法五个属性:
1、queryset
def get_queryset(self):
2、serializer_class
def get_serializer(self, *args, **kwargs):
def get_serializer_class(self):
3、filter_backends 配置过滤类 们
# 调用配置的过滤类完成过滤(都是在群查接口中完成,传入queryset,接收过滤后的queryset)
def filter_queryset(self, queryset):
4、pagination_class 配置分页类
# 调用配置的分页类完成分页(都是在群查接口中完成,传入queryset,接收分页过滤后的分页对象queryset)
def paginate_queryset(self, queryset):
5、
# 从pagination 中导入 基础分页,偏移分页,游标分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
1)PageNumberPagination 基础分页器的使用
方法一、
方法二、
1.在course文件夹中新建pagination文件
2.views中
2)LimitOffsetPagination 偏移分页器的使用
views文件
3) LimitOffsetPagination 游标分页器的使用
总结
过滤组件:
1、搜索过滤
views文件
总结:
2、排序过滤
总结:
3、自定义过滤组件
在course文件夹中新建filters文件
views文件
总结:
4、课程分类过滤
方法一:
01、项目终端:
pip install django-filter
02、views文件
3、总结
方法二、
views文件
总结:
方法三:区间过滤
views文件