課程模塊表結構

課程模塊

我們要開始寫課程模塊了~~課程模塊都有哪些功能呢~~

我們的課程模塊,包括了免費課程以及專題課程兩個方向~~

主要是課程的展示,點擊課程進入課程詳細頁面~~

課程詳細頁面展示,課程的概述,課程的價格策略,課程章節,評價以及常見問題~~

以及一些周邊的字段~~~這是主線路~~

根據功能設計表結構

對照著對標路飛網站,我們可以先討論下表結構~~

我們初步能夠確定下來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.titleclass 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.pngcategory = 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.titleclass Meta:verbose_name = "02-課程表"db_table = verbose_nameverbose_name_plural = verbose_nameclass 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.titleclass Meta:verbose_name = "03-課程詳細表"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):"""字段大體跟課程表相同,哪些不同根據業務邏輯去區分"""title = models.CharField(max_length=32, verbose_name="學位課程名字")def __str__(self):return self.titleclass Meta:verbose_name = "05-學位課程表"db_table = verbose_nameverbose_name_plural = verbose_nameclass 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.titleclass Meta:verbose_name = "06-課程章節表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_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_nameverbose_name_plural = verbose_nameunique_together = ('chapter', 'section_link')class PricePolicy(models.Model):"""價格策略表"""content_type = models.ForeignKey(ContentType)object_id = models.PositiveIntegerField()# 關聯course or degree_coursecontent_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_nameverbose_name_plural = verbose_nameunique_together = ("content_type", 'object_id', "valid_period")class OftenAskedQuestion(models.Model):"""常見問題"""content_type = models.ForeignKey(ContentType)  # 關聯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-常見問題表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_together = ('content_type', 'object_id', 'question')class Comment(models.Model):"""通用的評論表"""# 定位表content_type = models.ForeignKey(ContentType, blank=True, null=True)# 定位對象的idobject_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.contentclass Meta:verbose_name = "10-評價表"db_table = verbose_nameverbose_name_plural = verbose_nameclass Account(models.Model):username = models.CharField(max_length=32, verbose_name="用戶姓名")def __str__(self):return self.usernameclass Meta:verbose_name = "11-用戶表"db_table = verbose_nameverbose_name_plural = verbose_nameclass 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.titleclass Meta:verbose_name = "12-課程大綱表"db_table = verbose_nameverbose_name_plural = verbose_nameunique_together = ('course_detail', 'title')
課程模塊表結構

media配置

圖片位置需要在settings配置下

# media配置
MEDIA_URL = "media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
media 在settings配置下
from django.conf.urls import url, include
from django.contrib import admin
from app import settings
from django.views.static import serveurlpatterns = [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})
]
url也要加上

接口的編寫

圖片位置需要在settings配置下

我們表結構定下來以后,可以根據業務場景看需要哪些接口~~~

對于我們課程這個模塊,所有的功能都是展示,基于數據展示的,我們通常稱為數據接口~~

這種接口對于我們來說是最簡單的~~因為我們只是從數據庫拿數據~然后進行展示~~

我們來看下都需要哪些接口~~~

  -- 課程頁面? 有課程所有分類這個接口

  -- 課程頁面? 有展示課程的接口

  -- 點擊課程進入課程詳情頁面,詳情頁面的數據接口~~

  -- 詳情頁面下的子路由對應子組件的數據接口

    -- 課程章節課時

    -- 課程的評論

    -- 課程的常見問題

這些所有的數據接口~~套路都是讀取數據庫,序列化數據,返回~~~

那主要就是用DRF的序列化組件~~那我們從路由~然后序列化組件~然后看視圖~~

from django.conf.urls import url, include
from .views import CourseListView, CourseCategoryView, CourseDetailView, CourseChapterView
from .views import CourseCommentView, OftenAskedQuestionView# 在項目路由下做了一層分發
# url(r'^api/course/', include("course.urls")),
urlpatterns = [url(r"^$", CourseListView.as_view()),url(r"^category$", CourseCategoryView.as_view()),url(r"^detail/(?P<pk>\d+)$", CourseDetailView.as_view()),url(r"^(?P<pk>\d+)/chapters$", CourseChapterView.as_view()),url(r"^(?P<pk>\d+)/comment$", CourseCommentView.as_view()),url(r"^(?P<pk>\d+)/often-asked-question$", OftenAskedQuestionView.as_view()),
url
class CourseCategoryView(APIView):"""課程分類接口"""def get(self, request):queryset = Category.objects.all()ser_obj = CourseCategorySerializer(queryset, many=True)return Response(ser_obj.data)class CourseListView(APIView):"""查看所有免費課程的接口"""def get(self, request):category_id = request.query_params.get("category", 0)if category_id == 0:# 證明沒有分類,可以拿所有的課程數據queryset = Course.objects.all().order_by("order")else:queryset = Course.objects.filter(category_id=category_id).order_by("order")ser_obj = CourseSerializer(queryset, many=True)return Response(ser_obj.data)class CourseDetailView(APIView):"""課程詳情頁面"""def get(self, request, pk):course_detail_obj = CourseDetail.objects.filter(course__id=pk).first()if course_detail_obj:ser_obj = CourseDetailSerializer(course_detail_obj)return Response(ser_obj.data)else:return Response({"code": "1001", "msg": "查詢的課程不存在"})class CourseChapterView(APIView):"""課程章節接口"""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)class CourseCommentView(APIView):def get(self, request, pk):queryset = Course.objects.filter(pk=pk).first().course_comments.all()ser_obj = CourseCommentSerializer(queryset, many=True)return Response(ser_obj.data)class OftenAskedQuestionView(APIView):def get(self, request, pk):queryset = Course.objects.filter(pk=pk).first().often_ask_questions.all()ser_obj = OftenAskQuestionSerializer(queryset, many=True)return Response(ser_obj.data)
views
from rest_framework import serializers
from . import modelsclass CategorySerializers(serializers.ModelSerializer):class Meta:model = models.Categoryfields = "__all__"class CourseSerializers(serializers.ModelSerializer):# 有些字段自己重寫level = serializers.CharField(source="get_level_display")price = serializers.SerializerMethodField()def get_price(self, obj):price_policy_obj = obj.price_policy.all().order_by("price").first()# print(obj)# print(type(price_policy_obj))return price_policy_obj.pricecourse_img = serializers.SerializerMethodField()def get_course_img(self, obj):return "http://127.0.0.1:8000/media/" + str(obj.course_img)class Meta:model = models.Coursefields = ["id", "title", "course_img", "brief", "level", "study_num", "is_free", "price"]class CourseDetailSerializer(serializers.ModelSerializer):# 自己獲取字段title = serializers.SerializerMethodField()level = serializers.SerializerMethodField()study_num = serializers.SerializerMethodField()recommend_courses = serializers.SerializerMethodField()teachers = serializers.SerializerMethodField()outline = serializers.SerializerMethodField()  # 大綱price_policy = serializers.SerializerMethodField()def get_title(self, obj):return obj.course.titledef get_level(self, obj):return obj.course.get_level_display()def get_study_num(self, obj):return obj.course.study_numdef get_recommend_courses(self, obj):return [{"id": item.id, "title": item.title} for item in obj.recommend_courses.all()]def get_teachers(self, obj):return [{"id": teacher.id, "name": teacher.name, "brief": teacher.brief} for teacher in obj.teachers.all()]def get_outline(self, obj):return [{"id": item.id, "title": item.title, "content": item.content} for item inobj.course_outline.all().order_by("order")]def get_price_policy(self, obj):return [{"id": item.id, "valid_period": item.get_valid_period_display(), "price": item.price} for item inobj.course.price_policy.all().order_by("price")]class Meta:model = models.CourseDetail# fields = "__all__"exclude = ["course"]
serializers

我們的課程的視圖還可以重寫編寫一下~~利用我們之前學的視圖的封裝的那些類~~

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)
升級版視圖

我們可以根據上面的更改的視圖的示例~~來更改我們所有的視圖~~小伙伴們~自己動起手來吧~~

我們課程這個模塊下的數據接口我們就介紹這些~~

我們這里涉及課程圖片~~用我們Django的mediaURL~~

Django的MEDIA配置

STATIC_URL = '/static/'
# Media配置
MEDIA_URL = "media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
settings
from django.conf.urls import url, include
from django.contrib import admin
from django.views.static import serve
from new_luffy import settingsurlpatterns = [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})
]
urls

這樣我們上傳的圖片~數據庫存的是路徑地址~~我們前端向后端的media路徑發送請求~~

拿到我們想要的圖片,視頻等資源~~

轉載于:https://www.cnblogs.com/clbao/p/9998141.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250202.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250202.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250202.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue中computed、metfods、watch的區別

一、computed和methods 我們可以將同一函數定義為一個 method 或者一個計算屬性。對于最終的結果&#xff0c;兩種方式確實是相同的。 不同的是computed計算屬性是基于它們的依賴進行緩存的。計算屬性computed只有在它的相關依賴發生改變時才會重新求值。這就意味著只要計算依賴…

OI生涯回憶錄(二)

&#xff08;二&#xff09;NOIP2016之后到HLOI2017 之后變得有點頹廢&#xff0c;因為有的地方難度上來了&#xff0c;碰見不會的題我就會放挺。又或者有時候題水&#xff0c;改完了就不思進取了。到了過年前那幾天連著考了幾天試&#xff0c;好像是長春那邊冬令營&#xff08…

[tensorflow、神經網絡] - 使用tf和mnist訓練一個識別手寫數字模型,并測試

參考 包含: 1.層級的計算、2.訓練的整體流程、3.tensorboard畫圖、4.保存/使用模型、5.總體代碼(含詳細注釋) 1. 層級的計算 如上圖,mnist手寫數字識別的訓練集提供的圖片是 28 * 28 * 1的手寫圖像,初始識別的時候,并不知道一次要訓練多少個數據,因此輸入的規模為 [None, 784].…

面向過程、面向函數、面向對象的區別淺談

Python的面向過程、面向函數、面向對象的區別淺談 轉自--獵奇古今&#xff0c;加上其他 有人之前私信問我&#xff0c;python編程有面向過程、面向函數、面向對象三種&#xff0c;那么他們區別在哪呢&#xff1f; 面向過程就是將編程當成是做一件事&#xff0c;要按步驟完成&am…

js算法初窺06(算法模式03-函數式編程)

在解釋什么是函數式編程之前&#xff0c;我們先要說下什么是命令式編程&#xff0c;它們都屬于編程范式的一種。命令式編程其實就是一塊一塊的代碼&#xff0c;其中包括了我們要執行的邏輯或者判斷或者一些運算。也就是按部就班的一步一步完成我們所需要的邏輯。而函數式編程則…

[mmdetection] - win10配置mmdetection(1.1和2.0) + 訓練網絡(faster-rcnn、mask-rcnn)

pytorch配置 - 參考 mmdetextion 配置(win10) mmdetection訓練faster-rcnn (win10) mmdetection訓練mask-rcnn (win10) mmdetection 2.0配置(win10) mmdetection 2.0訓練Faster-RCNN&#xff08;win10) mmdetection 2.0全家桶訓練&#xff08;終結版) labelme安裝教程 l…

13、Spring Boot 2.x 多數據源配置

1.13 Spring Boot 2.x 多數據源配置 完整源碼&#xff1a; Spring-Boot-Demos轉載于:https://www.cnblogs.com/Grand-Jon/p/9999779.html

[pytorch、學習] - 3.5 圖像分類數據集

參考 3.5. 圖像分類數據集 在介紹shftmax回歸的實現前我們先引入一個多類圖像分類數據集 本章開始使用pytorch實現啦~ 本節我們將使用torchvision包,它是服務于PyTorch深度學習框架的,主要用來構建計算機視覺模型。torchvision主要由以下幾部分構成: torchvision.datasets: …

python自動化第三周---文件讀寫

1.python文件對象提供了三個“讀”方法&#xff1a; read()、readline() 和 readlines()。每種方法可以接受一個變量以限制每次讀取的數據量。 read() 每次讀取整個文件&#xff0c;它通常用于將文件內容放到一個字符串變量中。如果文件大于可用內存&#xff0c;為了保險起見&a…

最詳細的java泛型詳解

來源&#xff1a;最詳細的java泛型詳解 對java的泛型特性的了解僅限于表面的淺淺一層&#xff0c;直到在學習設計模式時發現有不了解的用法&#xff0c;才想起詳細的記錄一下。 本文參考java 泛型詳解、Java中的泛型方法、 java泛型詳解 1. 概述 泛型在java中有很重要的地位&a…

[pytorch、學習] - 3.6 softmax回歸的從零開始實現

參考 3.6 softmax回歸的從零開始實現 import torch import torchvision import numpy as np import sys sys.path.append("..") import d2lzh_pytorch as d2l3.6.1. 獲取和讀取數據 batch_size 256 train_iter, test_iter d2l.load_data_fashion_mnist(batch_si…

Django基礎必備三件套: HttpResponse render redirect

1. HttpResponse : 它的作用是內部傳入一個字符串參數, 然后發給瀏覽器 def index(request):return HttpResponse(ok) 2. render : 可以接收三個參數, 一是request參數, 二是待渲染的 html 模板文件, 三是保存具體數據的字典參數 def index(request):return render(request, …

React 簡單實例 (React-router + webpack + Antd )

React Demo Github 地址 經過React Native 的洗禮之后&#xff0c;寫了這個 demo &#xff1b;React 是為了使前端的V層更具組件化&#xff0c;能更好的復用&#xff0c;同時可以讓你從操作dom中解脫出來&#xff0c;只需要操作數據就會改變相應的dom&#xff1b; 而React Nat…

[pytorch、學習] - 3.7 softmax回歸的簡潔實現

參考 3.7. softmax回歸的簡潔實現 使用pytorch實現softmax import torch from torch import nn from torch.nn import init import numpy as np import sys sys.path.append("..") import d2lzh_pytorch as d2l3.7.1. 獲取和讀取數據 batch_size 256 train_iter…

【模板】NTT

NTT模板 #include<bits/stdc.h> using namespace std; #define LL long long const int MAXL22; const int MAXN1<<MAXL; const int Mod998244353; int rev[MAXN],A[MAXN],B[MAXN],C[MAXN]; int fast_pow(int a,int b){int ans1;while(b){if(b&1)ans1ll*ans*a%…

centos 7 php7 yum源

rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpmrpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm 轉載于:https://www.cnblogs.com/myJuly/p/10008252.html

[pytorch、學習] - 3.9 多重感知機的從零開始實現

參考 3.9 多重感知機的從零開始實現 import torch import numpy as np import sys sys.path.append("..") import d2lzh_pytorch as d2l3.9.1. 獲取和讀取數據 batch_size 256 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size)3.9.2. 定義模型參…

C語言逗號運算符和逗號表達式基礎總結

逗號運算符的作用&#xff1a; 1&#xff0c;起分隔符的作用&#xff1a; 定義變量用于分隔變量&#xff1a;int a,b輸入或輸出時用于分隔輸出表列 printf("%d%d",a,b) 2,用于逗號表達式的順序運算符 語法&#xff1a;表達式1&#xff0c;表達式2&#xff0c;...,表達…

java基礎-泛型舉例詳解

泛型 泛型是JDK5.0增加的新特性&#xff0c;泛型的本質是參數化類型&#xff0c;即所操作的數據類型被指定為一個參數。這種類型參數可以在類、接口、和方法的創建中&#xff0c;分別被稱為泛型類、泛型接口、泛型方法。 一、認識泛型 在沒有泛型之前,通過對類型Object的引用來…

MySQL數據庫視圖(view),視圖定義、創建視圖、修改視圖

原文鏈接&#xff1a;https://blog.csdn.net/moxigandashu/article/details/63254901轉載于:https://www.cnblogs.com/chrdai/p/9131881.html