博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
qhfl-3 Course模块
阅读量:5973 次
发布时间:2019-06-19

本文共 19100 字,大约阅读时间需要 63 分钟。

课程模块,包括免费课程以及专题课程两个,主要是课程的展示,点击课程进入课程详细页面

根据功能设计表结构

为了方便,每张表在数据库中添加了中文名

from django.db import modelsfrom django.contrib.contenttypes.fields import GenericForeignKey, GenericRelationfrom django.contrib.contenttypes.models import ContentType# from shopping.models import OrderDetail,Coupon# 注册admin 的时候 方便引入__all__ = ["Category", "Course", "CourseDetail", "Teacher", "DegreeCourse", "CourseChapter",           "CourseSection", "PricePolicy", "OftenAskedQuestion", "Comment", "Account", "CourseOutline"]class Category(models.Model):    """课程分类表"""    title = models.CharField(max_length=32, unique=True, verbose_name="课程的分类")    def __str__(self):        return self.title    class Meta:        verbose_name = "01-课程分类表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass Course(models.Model):    """课程表"""    title = models.CharField(max_length=128, unique=True, verbose_name="课程的名称")    course_img = models.ImageField(upload_to="course/%Y-%m", verbose_name='课程的图片')    category = models.ForeignKey(to="Category", verbose_name="课程的分类", on_delete=None)    COURSE_TYPE_CHOICES = ((0, "付费"), (1, "vip专享"), (2, "学位课程"),(3,"免费"))    course_type = models.SmallIntegerField(choices=COURSE_TYPE_CHOICES)    degree_course = models.ForeignKey(to="DegreeCourse", blank=True, null=True, help_text="如果是学位课程,必须关联学位表",                                      on_delete=None)    brief = models.CharField(verbose_name="课程简介", max_length=1024)    level_choices = ((0, '初级'), (1, '中级'), (2, '高级'))    level = models.SmallIntegerField(choices=level_choices, default=1)    status_choices = ((0, '上线'), (1, '下线'), (2, '预上线'))    status = models.SmallIntegerField(choices=status_choices, default=0)    pub_date = models.DateField(verbose_name="发布日期", blank=True, null=True)    order = models.IntegerField("课程顺序", help_text="从上一个课程数字往后排")    study_num = models.IntegerField(verbose_name="学习人数", help_text="只要有人买课程,订单表加入数据的同时给这个字段+1")    # order_details = GenericRelation("OrderDetail", related_query_name="course")    # coupon = GenericRelation("Coupon")    # 只用于反向查询不生成字段    price_policy = GenericRelation("PricePolicy")    often_ask_questions = GenericRelation("OftenAskedQuestion")    course_comments = GenericRelation("Comment")    def save(self, *args, **kwargs):        if self.course_type == 2:            if not self.degree_course:                raise ValueError("学位课必须关联学位课程表")        super(Course, self).save(*args, **kwargs)    def __str__(self):        return self.title    class Meta:        verbose_name = "02-课程表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass CourseDetail(models.Model):    """课程详细表"""    course = models.OneToOneField(to="Course", on_delete=None)    hours = models.IntegerField(verbose_name="课时", default=7)    course_slogan = models.CharField(max_length=125, blank=True, null=True, verbose_name="课程口号")    video_brief_link = models.CharField(max_length=255, blank=True, null=True)    summary = models.TextField(max_length=2048, verbose_name="课程概述")    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 self.course.title    class Meta:        verbose_name = "03-课程详细表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass Teacher(models.Model):    """讲师表"""    name = models.CharField(max_length=32, verbose_name="讲师名字")    brief = models.TextField(max_length=1024, verbose_name="讲师介绍")    def __str__(self):        return self.name    class Meta:        verbose_name = "04-教师表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass DegreeCourse(models.Model):    """    字段大体跟课程表相同,哪些不同根据业务逻辑去区分    """    title = models.CharField(max_length=32, verbose_name="学位课程名字")    def __str__(self):        return self.title    class Meta:        verbose_name = "05-学位课程表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass CourseChapter(models.Model):    """课程章节表"""    course = models.ForeignKey(to="Course", related_name="course_chapters", on_delete=None)    chapter = models.SmallIntegerField(default=1, verbose_name="第几章")    title = models.CharField(max_length=32, verbose_name="课程章节名称")    def __str__(self):        return self.title    class Meta:        verbose_name = "06-课程章节表"        db_table = verbose_name        verbose_name_plural = verbose_name        unique_together = ("course", "chapter")class CourseSection(models.Model):    """课时表"""    chapter = models.ForeignKey(to="CourseChapter", related_name="course_sections",verbose_name="self.chapter.course.title", on_delete=None)    title = models.CharField(max_length=32, verbose_name="课时")    section_order = models.SmallIntegerField(verbose_name="课时排序", help_text="建议每个课时之间空1至2个值,以备后续插入课时")    section_type_choices = ((0, '文档'), (1, '练习'), (2, '视频'))    free_trail = models.BooleanField("是否可试看", default=False)    section_type = models.SmallIntegerField(default=2, choices=section_type_choices)    section_link = models.CharField(max_length=255, blank=True, null=True, help_text="若是video,填vid,若是文档,填link")    def course_chapter(self):        return self.chapter.chapter    def course_name(self):        return self.chapter.course.title    def __str__(self):        return "%s-%s-%s课时" % (self.chapter.course,self.chapter, self.title)    class Meta:        verbose_name = "07-课程课时表"        db_table = verbose_name        verbose_name_plural = verbose_name        unique_together = ('chapter', 'section_link')class PricePolicy(models.Model):    """价格策略表"""    content_type = models.ForeignKey(ContentType, on_delete=None)  # 关联course or degree_course    object_id = models.PositiveIntegerField()    content_object = GenericForeignKey('content_type', 'object_id')    valid_period_choices = ((1, '1天'), (3, '3天'),                            (7, '1周'), (14, '2周'),                            (30, '1个月'),                            (60, '2个月'),                            (90, '3个月'),                            (120, '4个月'),                            (180, '6个月'), (210, '12个月'),                            (540, '18个月'), (720, '24个月'),                            (722, '24个月'), (723, '24个月'),                            )    valid_period = models.SmallIntegerField(choices=valid_period_choices)    price = models.FloatField()    def __str__(self):        return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price)    class Meta:        verbose_name = "08-价格策略表"        db_table = verbose_name        verbose_name_plural = verbose_name        unique_together = ("content_type", 'object_id', "valid_period")class OftenAskedQuestion(models.Model):    """常见问题"""    content_type = models.ForeignKey(ContentType, on_delete=None)  # 关联course or degree_course    object_id = models.PositiveIntegerField()    content_object = GenericForeignKey('content_type', 'object_id')    question = models.CharField(max_length=255)    answer = models.TextField(max_length=1024)    def __str__(self):        return "%s-%s" % (self.content_object, self.question)    class Meta:        verbose_name = "09-常见问题表"        db_table = verbose_name        verbose_name_plural = verbose_name        unique_together = ('content_type', 'object_id', 'question')class Comment(models.Model):    """通用的评论表"""    content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=None)    object_id = models.PositiveIntegerField(blank=True, null=True)    content_object = GenericForeignKey('content_type', 'object_id')    content = models.TextField(max_length=1024, verbose_name="评论内容")    account = models.ForeignKey("Account", verbose_name="会员名", on_delete=None)    date = models.DateTimeField(auto_now_add=True)    def __str__(self):        return self.content    class Meta:        verbose_name = "10-评价表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass Account(models.Model):    username = models.CharField(max_length=32, verbose_name="用户姓名")    pwd = models.CharField(max_length=32, verbose_name="密文密码")    # head_img = models.CharField(max_length=256, default='/static/frontend/head_portrait/logo@2x.png',    #                             verbose_name="个人头像")    balance = models.IntegerField(verbose_name="贝里余额", default=0)    def __str__(self):        return self.username    class Meta:        verbose_name = "11-用户表"        db_table = verbose_name        verbose_name_plural = verbose_nameclass CourseOutline(models.Model):    """    课程大纲    跟课程详情外键关联,而不是直接跟课程,提高查询    """    course_detail = models.ForeignKey(to="CourseDetail", related_name="course_outline", on_delete=None)    title = models.CharField(max_length=128)    order = models.PositiveSmallIntegerField(default=1)    # 前端显示顺序    content = models.TextField("内容", max_length=2048)    def __str__(self):        return "%s" % self.title    class Meta:        verbose_name = "12-课程大纲表"  #        db_table = verbose_name                         # 线上运行时不要写db_table        verbose_name_plural = verbose_name        unique_together = ('course_detail', 'title')  # 一个课程详情只有一个大纲
Course/models.py

 不要忘了注册到admin

from . import modelsfor table in models.__all__:    admin.site.register(getattr(models, table))

接口

对于课程这个模块,所有的功能都是展示,基于数据展示的,我们通常称为数据接口

这种接口对于我们来说是最简单的,从数据库拿数据,然后进行展示

需要的接口

  -- 课程页面  课程所有分类

        展示课程介绍的接口

  -- 点击课程进入课程详情页面,详情页面的数据接口

  -- 详情页面下的子路由对应子组件的数据接口

     课程章节课时

     课程的评论

     课程的常见问题

数据接口,都是读取数据库,序列化数据,返回

父路由分发path('api/course/', include("Course.urls")),

课程分类接口

from rest_framework import serializersfrom . import modelsclass CategorySerializer(serializers.ModelSerializer):    class Meta:        model = models.Category        fields = "__all__"

 

class CategoryView(APIView):    def get(self, request):        # 通过ORM操作获取所有分类数据        queryset = models.Category.objects.all()        # 利用序列化器去序列化我们的数据        ser_obj = CategorySerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)

 

课程详情接口

CourseDetailSerializer

 

path('detail/
', CourseDetailView.as_view()),class CourseDetailView(APIView): def get(self, request, pk): # 根据pk获取到课程详情对象 course_detail_obj = models.CourseDetail.objects.filter(course__id=pk).first() if not course_detail_obj: return Response({"code": 1001, "error": "查询的课程详情不存在"}) # 序列化课程详情 ser_obj = CourseDetailSerializer(course_detail_obj) # 返回 return Response(ser_obj.data)

 

 

课程章节接口

CourseChapterSerializer

 

class CourseChapterView(APIView):    def get(self, request, pk):        # ["第一章": {课时一, 课时二}]        queryset = models.CourseChapter.objects.filter(course_id=pk).all().order_by("chapter")        # 序列化章节对象        ser_obj = CourseChapterSerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)

评论以及常见问题接口

class CourseCommentSerializer(serializers.ModelSerializer):    account = serializers.CharField(source="account.username")    class Meta:        model = models.Comment        fields = ["id", "account", "content", "date"]class QuestionSerializer(serializers.ModelSerializer): class Meta: model = models.OftenAskedQuestion fields = ["id", "question", "answer"]

 

class CourseCommentView(APIView):    def get(self, request, pk):        # 通过课程id找到课程所有的评论        queryset = models.Course.objects.filter(id=pk).first().course_comments.all()        # 序列化        ser_obj = CourseCommentSerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)class QuestionView(APIView): def get(self, request, pk): queryset = models.Course.objects.filter(id=pk).first().often_ask_questions.all() ser_obj = QuestionSerializer(queryset, many=True) return Response(ser_obj.data)

 

from django.urls import pathfrom .views import CategoryView, CourseView, CourseDetailView, CourseChapterView, CourseCommentView, QuestionViewfrom .video_view import PolyvViewurlpatterns = [    # 课程分类    path('category', CategoryView.as_view()),    # 课程    path('list', CourseView.as_view()),    #               课程id    path('detail/
', CourseDetailView.as_view()), # 课程的章节接口 课程id path('chapter/
', CourseChapterView.as_view()), # 评论 课程id path('comment/
', CourseCommentView.as_view()), path('question/
', QuestionView.as_view()), path('polyv', PolyvView.as_view()),]
Course/urls.py
from rest_framework import serializersfrom . import modelsclass CategorySerializer(serializers.ModelSerializer):    class Meta:        model = models.Category        fields = "__all__"class CourseSerializer(serializers.ModelSerializer):    level = serializers.CharField(source="get_level_display")  # 直接将选项的数字,转换成了可显示的字符    price = serializers.SerializerMethodField()    def get_price(self, obj):        print(obj.price_policy.all())        return obj.price_policy.all().order_by("price").first().price    class Meta:        model = models.Course        fields = ["id", "title", "course_img", "brief", "level", "study_num", "price"]class CourseDetailSerializer(serializers.ModelSerializer):    level = serializers.CharField(source="course.get_level_display") # level 是选项时 get_xx_display 直接拿到选项的值    study_num = serializers.IntegerField(source="course.study_num")    recommend_courses = serializers.SerializerMethodField()  # 涉及到跨表,用    teachers = serializers.SerializerMethodField()    price_policy = serializers.SerializerMethodField()    course_outline = serializers.SerializerMethodField()    def get_course_outline(self, obj): # obj是课程对象        return [{"id": outline.id, "title": outline.title, "content": outline.content} for outline in                obj.course_outline.all().order_by("order")]    def get_price_policy(self, obj):        return [{"id": price.id, "valid_price_display": price.get_valid_period_display(), "price": price.price} for                price in obj.course.price_policy.all()]    def get_teachers(self, obj):        return [{"id": teacher.id, "name": teacher.name} for teacher in obj.teachers.all()]    def get_recommend_courses(self, obj):        return [{"id": course.id, "title": course.title} for course in obj.recommend_courses.all()]    class Meta:        model = models.CourseDetail        fields = ["id", "hours", "summary", "level", "study_num", "recommend_courses", "teachers",                  "price_policy", "course_outline"]class CourseChapterSerializer(serializers.ModelSerializer):    sections = serializers.SerializerMethodField()    def get_sections(self, obj):        return [{"id": section.id, "title": section.title, "free_trail": section.free_trail} for section in                obj.course_sections.all().order_by("section_order")]    class Meta:        model = models.CourseChapter        fields = ["id", "title", "sections"]class CourseCommentSerializer(serializers.ModelSerializer):    account = serializers.CharField(source="account.username")    class Meta:        model = models.Comment        fields = ["id", "account", "content", "date"]class QuestionSerializer(serializers.ModelSerializer):    class Meta:        model = models.OftenAskedQuestion        fields = ["id", "question", "answer"]
Course/serializers.py
from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom . import modelsfrom .serializers import CategorySerializer, CourseSerializer, CourseDetailSerializer, CourseChapterSerializerfrom .serializers import CourseCommentSerializer, QuestionSerializerclass CategoryView(APIView):    def get(self, request):        # 通过ORM操作获取所有分类数据        queryset = models.Category.objects.all()        # 利用序列化器去序列化我们的数据        ser_obj = CategorySerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)class CourseView(APIView):    def get(self, request):        # 获取过滤条件中的分类ID        category_id = request.query_params.get("category", 0)        # 根据分类获取课程        if category_id == 0:            queryset = models.Course.objects.all().order_by("order")        else:            queryset = models.Course.objects.filter(category_id=category_id).all().order_by("order")        # 序列化课程数据        ser_obj = CourseSerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)class CourseDetailView(APIView):    def get(self, request, pk):        # 根据pk获取到课程详情对象        course_detail_obj = models.CourseDetail.objects.filter(course__id=pk).first()        if not course_detail_obj:            return Response({"code": 1001, "error": "查询的课程详情不存在"})        # 序列化课程详情        ser_obj = CourseDetailSerializer(course_detail_obj)        # 返回        return Response(ser_obj.data)class CourseChapterView(APIView):    def get(self, request, pk):        # ["第一章": {课时一, 课时二}]        queryset = models.CourseChapter.objects.filter(course_id=pk).all().order_by("chapter")        # 序列化章节对象        ser_obj = CourseChapterSerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)class CourseCommentView(APIView):    def get(self, request, pk):        # 通过课程id找到课程所有的评论        queryset = models.Course.objects.filter(id=pk).first().course_comments.all()        # 序列化        ser_obj = CourseCommentSerializer(queryset, many=True)        # 返回        return Response(ser_obj.data)class QuestionView(APIView):    def get(self, request, pk):        queryset = models.Course.objects.filter(id=pk).first().often_ask_questions.all()        ser_obj = QuestionSerializer(queryset, many=True)        return Response(ser_obj.data)
Course/views.py
class CourseCategoryView(generics.ListAPIView):    queryset = Category.objects.all()    serializer_class = CourseCategorySerializer    """课程分类接口"""    # def get(self, request):    #     queryset = Category.objects.all()    #     ser_obj = CourseCategorySerializer(queryset, many=True)    #     return Response(ser_obj.data)class CourseChapterView(generics.RetrieveAPIView):    queryset = CourseChapter.objects.all()    serializer_class = CourseChapterSerializer    # 指定过滤的类 用排序的过滤类    filter_backends = (filters.OrderingFilter,)    # 排序的字段    ordering = ("chapter",)    # def get(self, request, pk):    #     # 首先我们要清楚数据结构    #     # 我们要的是[章节一:{课时,课时2}]    #     queryset = CourseChapter.objects.filter(course_id=pk).order_by("chapter")    #     ser_obj = CourseChapterSerializer(queryset, many=True)    #     return Response(ser_obj.data)升级版视图的示例
Course/views.py 优化

 

Django的MEDIA配置

# settings.pySTATIC_URL = '/static/'# Media配置MEDIA_URL = "media/"MEDIA_ROOT = os.path.join(BASE_DIR, "media")

 

# urls.pyfrom django.conf.urls import url, includefrom django.contrib import adminfrom django.views.static import servefrom new_luffy import settings
# media路径配置re_path('media/(?P
.*)', serve, {'document_root': settings.MEDIA_ROOT})

 

上传的图片,数据库存的是路径地址,前端向后端的media路径发送请求。

线上环境时可以将 MEDIA_ROOT 存放到nginx的静态资源文件夹下面

转载于:https://www.cnblogs.com/wenyule/p/10467637.html

你可能感兴趣的文章
HTML思维导图
查看>>
git改密码出现授权问题
查看>>
ORA-02266: 表中的唯一/主键被启用的外键引用
查看>>
day-6 and day-7:面向对象
查看>>
CSU Double Shortest Paths 湖南省第十届省赛
查看>>
webgl像机世界
查看>>
php正则怎么使用(最全最细致)
查看>>
javascript数学运算符
查看>>
LC.155. Min Stack(非优化,两个stack 同步 + -)
查看>>
交互设计[3]--点石成金
查看>>
SCCM TP4部署Office2013
查看>>
SVN: bdb: BDB1538 Program version 5.3 doesn't match environment version 4.7
查看>>
jsp内置对象作业3-application用户注册
查看>>
redis主从配置<转>
查看>>
bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理...
查看>>
Web应用工作原理、动态网页技术
查看>>
EXCEL工作表保护密码破解 宏撤销保护图文教程
查看>>
Catalan数(卡特兰数)
查看>>
python 数据库中文乱码 Excel
查看>>
利用console控制台调试php代码
查看>>