course/urls.py
from django.urls import path, re_path, include from . import views from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('categories',views.CourseCategoryView,'categories') urlpatterns = [ path('', include(router.urls)), ]
course/views.py
from rest_framework.viewsets import GenericViewSet from rest_framework.mixins import ListModelMixin from . import models from . import serializer # 课程分类群查接口 class CourseCategoryView(GenericViewSet,ListModelMixin): queryset = models.CourseCategory.objects.filter( is_delete=False,is_show=True).order_by('orders').all() serializer_class = serializer.CourseCategorySerializer
course/serializer.py
from rest_framework import serializers from . import models class CourseCategorySerializer(serializers.ModelSerializer): class Meta: model = models.CourseCategory fields = ['id','name']
course/urls.py
from django.urls import path, re_path, include from . import views from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('categories', views.CourseCategoryView, 'categories') router.register('free', views.CouresView, 'free') urlpatterns = [ path('', include(router.urls)), ]
course/views.py
# 课程群查接口 from rest_framework.viewsets import GenericViewSet from rest_framework.mixins import ListModelMixin from .num_pagenation import PageNumberPagination from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter,SearchFilter from . import models from . import serializer class CoursesView(GenericViewSet,ListModelMixin): queryset = models.Course.objects.filter( is_delete=False, is_show=True).order_by('orders').all() serializer_class = serializer.CoursesModelSerializer # 分页 pagination_class = PageNumberPagination filter_backends = [DjangoFilterBackend,OrderingFilter,SearchFilter] ordering_fields = ['id','price','students'] # 通过关键字筛选 search_fields = ['id','name','brief'] filter_fields = ['course_category','students']
course/serializer.py
from rest_framework import serializers from . import models class CourseCategorySerializer(serializers.ModelSerializer): class Meta: model = models.CourseCategory fields = ['id','name'] # 写一个teacher的序列化器作为课程序列化器的子序列化器 class TeacherSerializer(serializers.ModelSerializer): class Meta: model = models.Teacher fields = ['id','name','role_name','signature','image','brief'] class CoursesModelSerializer(serializers.ModelSerializer): # 通过子序列化的方式 获取teacher字段的详情数据 teacher = TeacherSerializer() class Meta: model = models.Course fields = [ 'id', 'name', 'course_img', 'brief', 'attachment_path', 'pub_sections', 'price', 'students', 'period', 'sections', 'course_type_name', 'level_name', 'status_name', 'teacher', 'section_list', ]
course/models.py
# course/models.py class Course(BaseModel): ... @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): ll=[] # 根据课程取出所有章节(正向查询,字段名.all()) course_chapter_list=self.coursechapters.all() for course_chapter in course_chapter_list: # 通过章节对象,取到章节下所有的课时(反向查询) # course_chapter.表名小写_set.all() 现在变成了course_chapter.coursesections.all() course_sections_list=course_chapter.coursesections.all() for course_section in course_sections_list: ll.append({ 'name': course_section.name, 'section_link': course_section.section_link, 'duration': course_section.duration, 'free_trail': course_section.free_trail, }) if len(ll)>=4: return ll return ll class Teacher(BaseModel): ... def role_name(self): # 返回角色的中文 return self.get_role_display()
course/models.py详细列表
from django.db import models from utils.models 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="付费类型") # 课程介绍(bbs的文章内容) 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) #建议学习周期 period = models.IntegerField(verbose_name="建议学习周期(day)", default=7) # 文档(zip,课程资料) 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="课程状态") # 学习人数 students = models.IntegerField(verbose_name="学习人数", default=0) #总课时数量 sections = models.IntegerField(verbose_name="总课时数量", default=0) # 课时更新数量 pub_sections = models.IntegerField(verbose_name="课时更新数量", default=0) price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="课程原价", default=0) # 课程分类,跟分类表一对多,关联字段写在多的一方 # db_constraint=False:实际编码中,外键关联是人为约束,不是直接使用关联 # 不建立外键,但是orm使用跟之前一样 # blank=True 后台管理,录入的时候,blank=True可以为空 course_category = models.ForeignKey('CourseCategory', on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True, verbose_name="课程分类") # 一套课程是一个老师讲,一对多 teacher = models.ForeignKey("Teacher", on_delete=models.DO_NOTHING, null=True,db_constraint=False, blank=True, verbose_name="授课老师") class Meta: db_table = "luffy_course" verbose_name = "课程" verbose_name_plural = "课程" def __str__(self): return "%s" % self.name @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): ll = [] # 获取章节列表 chapter_list = self.coursechapters.all() for chapter in chapter_list: course_section_list = chapter.coursesections.all() for course_section in course_section_list: ll.append({'name':course_section.name, 'section_link':course_section.section_link, 'duration': course_section.duration, 'free_trail': course_section.free_trail, }) if len(ll) >= 4: return ll return ll 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="导师描述") class Meta: db_table = "luffy_teacher" verbose_name = "导师" verbose_name_plural = verbose_name def __str__(self): return "%s" % self.name def role_name(self): return self.get_role_display() class CourseChapter(BaseModel): """章节""" # 一对多,章节多 # related_name:基于对象的跨表查询,反向操作替换掉 表名小写_set.all() # related_query_name:反向查询操作时,使用的连接前缀,用于替换表名 course = models.ForeignKey("Course", related_name='coursechapters', on_delete=models.CASCADE, verbose_name="课程名称") # 第几章 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): return "%s:(第%s章)%s" % (self.course, 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="课程章节") 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): return "%s-%s" % (self.chapter, self.name)
''' 排序: from rest_framework.filters import OrderingFilter,SearchFilter 按id正序倒叙排序,按price正序倒叙排列 使用:http://127.0.0.1:8000/course/free/?ordering=-id 配置类: filter_backends=[OrderingFilter] 配置字段: ordering_fields=['id','price'] 内置过滤: from rest_framework.filters import OrderingFilter,SearchFilter 使用:http://127.0.0.1:8000/course/free/?search=39 按照price过滤(表自有的字段直接过滤) 配置类: filter_backends=[SearchFilter] 配置字段: search_fields=['price'] 扩展:django-filter 安装:pip install django-filter 注册:在settings配置注册应用中注册:'django_filters' 支持自由字段的过滤还支持外键字段的过滤 from django_filters.rest_framework import DjangoFilterBackend http://127.0.0.1:8000/course/free/?course_category=1 # 过滤分类为1 (python的所有课程) 配置类: filter_backends=[DjangoFilterBackend] 配置字段: filter_fields=['course_category'] '''