日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

qhfl-3 Course模块

發(fā)布時(shí)間:2024/9/3 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 qhfl-3 Course模块 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

課程模塊,包括免費(fèi)課程以及專題課程兩個(gè),主要是課程的展示,點(diǎn)擊課程進(jìn)入課程詳細(xì)頁(yè)面

根據(jù)功能設(shè)計(jì)表結(jié)構(gòu)

為了方便,每張表在數(shù)據(jù)庫(kù)中添加了中文名

from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType # from shopping.models import OrderDetail,Coupon# 注冊(cè)admin 的時(shí)候 方便引入 __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.titleclass Meta:verbose_name = "01-課程分類表"db_table = verbose_nameverbose_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, "付費(fèi)"), (1, "vip專享"), (2, "學(xué)位課程"),(3,"免費(fèi)"))course_type = models.SmallIntegerField(choices=COURSE_TYPE_CHOICES)degree_course = models.ForeignKey(to="DegreeCourse", blank=True, null=True, help_text="如果是學(xué)位課程,必須關(guān)聯(lián)學(xué)位表",on_delete=None)brief = models.CharField(verbose_name="課程簡(jiǎn)介", max_length=1024)level_choices = ((0, '初級(jí)'), (1, '中級(jí)'), (2, '高級(jí)'))level = models.SmallIntegerField(choices=level_choices, default=1)status_choices = ((0, '上線'), (1, '下線'), (2, '預(yù)上線'))status = models.SmallIntegerField(choices=status_choices, default=0)pub_date = models.DateField(verbose_name="發(fā)布日期", blank=True, null=True)order = models.IntegerField("課程順序", help_text="從上一個(gè)課程數(shù)字往后排")study_num = models.IntegerField(verbose_name="學(xué)習(xí)人數(shù)", help_text="只要有人買課程,訂單表加入數(shù)據(jù)的同時(shí)給這個(gè)字段+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("學(xué)位課必須關(guān)聯(lián)學(xué)位課程表")super(Course, self).save(*args, **kwargs)def __str__(self):return self.titleclass Meta:verbose_name = "02-課程表"db_table = verbose_nameverbose_name_plural = verbose_nameclass CourseDetail(models.Model):"""課程詳細(xì)表"""course = models.OneToOneField(to="Course", on_delete=None)hours = models.IntegerField(verbose_name="課時(shí)", default=7)course_slogan = models.CharField(max_length=125, blank=True, null=True, verbose_name="課程口號(hào)")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="為什么學(xué)習(xí)這門課程")what_to_study_brief = models.TextField(verbose_name="我將學(xué)到哪些內(nèi)容")career_improvement = models.TextField(verbose_name="此項(xiàng)目如何有助于我的職業(yè)生涯")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.titleclass Meta:verbose_name = "03-課程詳細(xì)表"db_table = verbose_nameverbose_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.nameclass Meta:verbose_name = "04-教師表"db_table = verbose_nameverbose_name_plural = verbose_nameclass DegreeCourse(models.Model):"""字段大體跟課程表相同,哪些不同根據(jù)業(yè)務(wù)邏輯去區(qū)分"""title = models.CharField(max_length=32, verbose_name="學(xué)位課程名字")def __str__(self):return self.titleclass Meta:verbose_name = "05-學(xué)位課程表"db_table = verbose_nameverbose_name_plural = verbose_nameclass CourseChapter(models.Model):"""課程章節(jié)表"""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="課程章節(jié)名稱")def __str__(self):return self.titleclass Meta:verbose_name = "06-課程章節(jié)表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_together = ("course", "chapter")class CourseSection(models.Model):"""課時(shí)表"""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="課時(shí)")section_order = models.SmallIntegerField(verbose_name="課時(shí)排序", help_text="建議每個(gè)課時(shí)之間空1至2個(gè)值,以備后續(xù)插入課時(shí)")section_type_choices = ((0, '文檔'), (1, '練習(xí)'), (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.chapterdef course_name(self):return self.chapter.course.titledef __str__(self):return "%s-%s-%s課時(shí)" % (self.chapter.course,self.chapter, self.title)class Meta:verbose_name = "07-課程課時(shí)表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_together = ('chapter', 'section_link')class PricePolicy(models.Model):"""價(jià)格策略表"""content_type = models.ForeignKey(ContentType, on_delete=None) # 關(guān)聯(lián)course or degree_courseobject_id = models.PositiveIntegerField()content_object = GenericForeignKey('content_type', 'object_id')valid_period_choices = ((1, '1天'), (3, '3天'),(7, '1周'), (14, '2周'),(30, '1個(gè)月'),(60, '2個(gè)月'),(90, '3個(gè)月'),(120, '4個(gè)月'),(180, '6個(gè)月'), (210, '12個(gè)月'),(540, '18個(gè)月'), (720, '24個(gè)月'),(722, '24個(gè)月'), (723, '24個(gè)月'),)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-價(jià)格策略表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_together = ("content_type", 'object_id', "valid_period")class OftenAskedQuestion(models.Model):"""常見(jiàn)問(wèn)題"""content_type = models.ForeignKey(ContentType, on_delete=None) # 關(guān)聯(lián)course or degree_courseobject_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-常見(jiàn)問(wèn)題表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_together = ('content_type', 'object_id', 'question')class Comment(models.Model):"""通用的評(píng)論表"""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="評(píng)論內(nèi)容")account = models.ForeignKey("Account", verbose_name="會(huì)員名", on_delete=None)date = models.DateTimeField(auto_now_add=True)def __str__(self):return self.contentclass Meta:verbose_name = "10-評(píng)價(jià)表"db_table = verbose_nameverbose_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="個(gè)人頭像")balance = models.IntegerField(verbose_name="貝里余額", default=0)def __str__(self):return self.usernameclass Meta:verbose_name = "11-用戶表"db_table = verbose_nameverbose_name_plural = verbose_nameclass CourseOutline(models.Model):"""課程大綱跟課程詳情外鍵關(guān)聯(lián),而不是直接跟課程,提高查詢"""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("內(nèi)容", max_length=2048)def __str__(self):return "%s" % self.titleclass Meta:verbose_name = "12-課程大綱表" #db_table = verbose_name # 線上運(yùn)行時(shí)不要寫db_tableverbose_name_plural = verbose_nameunique_together = ('course_detail', 'title') # 一個(gè)課程詳情只有一個(gè)大綱 Course/models.py

?不要忘了注冊(cè)到admin

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

接口

對(duì)于課程這個(gè)模塊,所有的功能都是展示,基于數(shù)據(jù)展示的,我們通常稱為數(shù)據(jù)接口

這種接口對(duì)于我們來(lái)說(shuō)是最簡(jiǎn)單的,從數(shù)據(jù)庫(kù)拿數(shù)據(jù),然后進(jìn)行展示

需要的接口

  -- 課程頁(yè)面? 課程所有分類

        展示課程介紹的接口

  -- 點(diǎn)擊課程進(jìn)入課程詳情頁(yè)面,詳情頁(yè)面的數(shù)據(jù)接口

  -- 詳情頁(yè)面下的子路由對(duì)應(yīng)子組件的數(shù)據(jù)接口

     課程章節(jié)課時(shí)

     課程的評(píng)論

     課程的常見(jiàn)問(wèn)題

數(shù)據(jù)接口,都是讀取數(shù)據(jù)庫(kù),序列化數(shù)據(jù),返回

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

課程分類接口

from rest_framework import serializers from . import modelsclass CategorySerializer(serializers.ModelSerializer):class Meta:model = models.Categoryfields = "__all__" class CategoryView(APIView):def get(self, request):# 通過(guò)ORM操作獲取所有分類數(shù)據(jù)queryset = models.Category.objects.all()# 利用序列化器去序列化我們的數(shù)據(jù)ser_obj = CategorySerializer(queryset, many=True)# 返回return Response(ser_obj.data)

課程詳情接口

CourseDetailSerializer path('detail/<int:pk>', CourseDetailView.as_view()),class CourseDetailView(APIView):def get(self, request, pk):# 根據(jù)pk獲取到課程詳情對(duì)象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)

課程章節(jié)接口

CourseChapterSerializer class CourseChapterView(APIView):def get(self, request, pk):# ["第一章": {課時(shí)一, 課時(shí)二}]queryset = models.CourseChapter.objects.filter(course_id=pk).all().order_by("chapter")# 序列化章節(jié)對(duì)象ser_obj = CourseChapterSerializer(queryset, many=True)# 返回return Response(ser_obj.data)

評(píng)論以及常見(jiàn)問(wèn)題接口

class CourseCommentSerializer(serializers.ModelSerializer):account = serializers.CharField(source="account.username")class Meta:model = models.Commentfields = ["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):# 通過(guò)課程id找到課程所有的評(píng)論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 path from .views import CategoryView, CourseView, CourseDetailView, CourseChapterView, CourseCommentView, QuestionView from .video_view import PolyvViewurlpatterns = [# 課程分類path('category', CategoryView.as_view()),# 課程path('list', CourseView.as_view()),# 課程idpath('detail/<int:pk>', CourseDetailView.as_view()),# 課程的章節(jié)接口 課程idpath('chapter/<int:pk>', CourseChapterView.as_view()),# 評(píng)論 課程idpath('comment/<int:pk>', CourseCommentView.as_view()),path('question/<int:pk>', QuestionView.as_view()),path('polyv', PolyvView.as_view()),] Course/urls.py from rest_framework import serializers from . import modelsclass CategorySerializer(serializers.ModelSerializer):class Meta:model = models.Categoryfields = "__all__"class CourseSerializer(serializers.ModelSerializer):level = serializers.CharField(source="get_level_display") # 直接將選項(xiàng)的數(shù)字,轉(zhuǎn)換成了可顯示的字符price = serializers.SerializerMethodField()def get_price(self, obj):print(obj.price_policy.all())return obj.price_policy.all().order_by("price").first().priceclass Meta:model = models.Coursefields = ["id", "title", "course_img", "brief", "level", "study_num", "price"]class CourseDetailSerializer(serializers.ModelSerializer):level = serializers.CharField(source="course.get_level_display") # level 是選項(xiàng)時(shí) get_xx_display 直接拿到選項(xiàng)的值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是課程對(duì)象return [{"id": outline.id, "title": outline.title, "content": outline.content} for outline inobj.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} forprice 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.CourseDetailfields = ["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 inobj.course_sections.all().order_by("section_order")]class Meta:model = models.CourseChapterfields = ["id", "title", "sections"]class CourseCommentSerializer(serializers.ModelSerializer):account = serializers.CharField(source="account.username")class Meta:model = models.Commentfields = ["id", "account", "content", "date"]class QuestionSerializer(serializers.ModelSerializer):class Meta:model = models.OftenAskedQuestionfields = ["id", "question", "answer"] Course/serializers.py from rest_framework.views import APIView from rest_framework.response import Response from . import models from .serializers import CategorySerializer, CourseSerializer, CourseDetailSerializer, CourseChapterSerializer from .serializers import CourseCommentSerializer, QuestionSerializerclass CategoryView(APIView):def get(self, request):# 通過(guò)ORM操作獲取所有分類數(shù)據(jù)queryset = models.Category.objects.all()# 利用序列化器去序列化我們的數(shù)據(jù)ser_obj = CategorySerializer(queryset, many=True)# 返回return Response(ser_obj.data)class CourseView(APIView):def get(self, request):# 獲取過(guò)濾條件中的分類IDcategory_id = request.query_params.get("category", 0)# 根據(jù)分類獲取課程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")# 序列化課程數(shù)據(jù)ser_obj = CourseSerializer(queryset, many=True)# 返回return Response(ser_obj.data)class CourseDetailView(APIView):def get(self, request, pk):# 根據(jù)pk獲取到課程詳情對(duì)象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):# ["第一章": {課時(shí)一, 課時(shí)二}]queryset = models.CourseChapter.objects.filter(course_id=pk).all().order_by("chapter")# 序列化章節(jié)對(duì)象ser_obj = CourseChapterSerializer(queryset, many=True)# 返回return Response(ser_obj.data)class CourseCommentView(APIView):def get(self, request, pk):# 通過(guò)課程id找到課程所有的評(píng)論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# 指定過(guò)濾的類 用排序的過(guò)濾類filter_backends = (filters.OrderingFilter,)# 排序的字段ordering = ("chapter",)# def get(self, request, pk):# # 首先我們要清楚數(shù)據(jù)結(jié)構(gòu)# # 我們要的是[章節(jié)一:{課時(shí),課時(shí)2}]# queryset = CourseChapter.objects.filter(course_id=pk).order_by("chapter")# ser_obj = CourseChapterSerializer(queryset, many=True)# return Response(ser_obj.data)升級(jí)版視圖的示例 Course/views.py 優(yōu)化

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, include from django.contrib import admin from django.views.static import serve from new_luffy import settings # media路徑配置 re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})

上傳的圖片,數(shù)據(jù)庫(kù)存的是路徑地址,前端向后端的media路徑發(fā)送請(qǐng)求。

線上環(huán)境時(shí)可以將 MEDIA_ROOT 存放到nginx的靜態(tài)資源文件夾下面

總結(jié)

以上是生活随笔為你收集整理的qhfl-3 Course模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。