课程模块表结构
Posted clbao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了课程模块表结构相关的知识,希望对你有一定的参考价值。
课程模块
我们要开始写课程模块了~~课程模块都有哪些功能呢~~
我们的课程模块,包括了免费课程以及专题课程两个方向~~
主要是课程的展示,点击课程进入课程详细页面~~
课程详细页面展示,课程的概述,课程的价格策略,课程章节,评价以及常见问题~~
以及一些周边的字段~~~这是主线路~~
根据功能设计表结构
对照着对标路飞网站,我们可以先讨论下表结构~~
我们初步能够确定下来12张表~~
from django.db import models from django.contrib.contenttypes.fields import GenericRelation, GenericForeignKey from django.contrib.contenttypes.models import ContentType # Create your models here. __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_name # 复数 class Course(models.Model): """课程表""" title = models.CharField(max_length=128, unique=True, verbose_name="课程的名称") course_img = models.ImageField(upload_to="course/%Y-%m", verbose_name=‘课程的图片‘) # media/course/2018-11/xxx.png category = models.ForeignKey(to="Category", verbose_name="课程的分类") COURSE_TYPE_CHOICES = ((0, "付费"), (1, "vip专享"), (2, "学位课程")) course_type = models.SmallIntegerField(choices=COURSE_TYPE_CHOICES) degree_course = models.ForeignKey(to="DegreeCourse", blank=True, null=True, help_text="如果是学位课程,必须关联学位表") # course_type degree_course_id # 0 null # 1 null # 2 2 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(verbose_name="课程顺序", help_text="从上一个课程数字往后排, 建议中间空几个数字") study_num = models.IntegerField(verbose_name="学习人数", help_text="只要有人买课程,订单表加入数据的同时给这个字段+1") is_free = models.BooleanField(default=False) # 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_name class CourseDetail(models.Model): """课程详细表""" course = models.OneToOneField(to="Course") hours = models.IntegerField(verbose_name="课时") 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="为什么学习这门课程") service = 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_name class 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_name class 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_name class CourseChapter(models.Model): """课程章节表""" course = models.ForeignKey(to="Course", related_name="course_chapters") # 排序用的 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") 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 __str__(self): return "%s-%s" % (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) object_id = models.PositiveIntegerField() # 关联course or degree_course 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个月‘) ) 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) # 关联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) # 定位对象的id 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="会员名") 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_name class Account(models.Model): username = models.CharField(max_length=32, verbose_name="用户姓名") def __str__(self): return self.username class Meta: verbose_name = "11-用户表" db_table = verbose_name verbose_name_plural = verbose_name class CourseOutline(models.Model): """课程大纲""" course_detail = models.ForeignKey(to="CourseDetail", related_name="course_outline") 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 verbose_name_plural = verbose_name unique_together = (‘course_detail‘, ‘title‘)
media配置
图片位置需要在settings配置下
# media配置 MEDIA_URL = "media/" MEDIA_ROOT = os.path.join(BASE_DIR, "media")
from django.conf.urls import url, include from django.contrib import admin from app import settings from django.views.static import serve urlpatterns = [ url(r‘^admin/‘, admin.site.urls), url(r‘^api/course/‘, include("course.urls")), # media路径配置 url(r‘media/(?P<path>.*)$‘, serve, {‘document_root‘: settings.MEDIA_ROOT}) ]
接口的编写
图片位置需要在settings配置下
我们表结构定下来以后,可以根据业务场景看需要哪些接口~~~
对于我们课程这个模块,所有的功能都是展示,基于数据展示的,我们通常称为数据接口~~
这种接口对于我们来说是最简单的~~因为我们只是从数据库拿数据~然后进行展示~~
我们来看下都需要哪些接口~~~
-- 课程页面 有课程所有分类这个接口
-- 课程页面 有展示课程的接口
-- 点击课程进入课程详情页面,详情页面的数据接口~~
-- 详情页面下的子路由对应子组件的数据接口
-- 课程章节课时
-- 课程的评论
-- 课程的常见问题
这些所有的数据接口~~套路都是读取数据库,序列化数据,返回~~~
那主要就是用DRF的序列化组件~~那我们从路由~然后序列化组件~然后看视图~~
我们的课程的视图还可以重写编写一下~~利用我们之前学的视图的封装的那些类~~
我们可以根据上面的更改的视图的示例~~来更改我们所有的视图~~小伙伴们~自己动起手来吧~~
我们课程这个模块下的数据接口我们就介绍这些~~
我们这里涉及课程图片~~用我们Django的mediaURL~~
Django的MEDIA配置
# settings.py STATIC_URL = ‘/static/‘ # Media配置 MEDIA_URL = "media/" MEDIA_ROOT = os.path.join(BASE_DIR, "media")
这样我们上传的图片~数据库存的是路径地址~~我们前端向后端的media路径发送请求~~
拿到我们想要的图片,视频等资源~~
以上是关于课程模块表结构的主要内容,如果未能解决你的问题,请参考以下文章
路飞项目搭建5 课程模块: 表设计,表关系优化,群查接口模块(分页组件,搜索组件,排序组件)