1、vue項目目錄介紹前端
src目錄:vue
assets目錄:防止靜態文件,和django的static相似。node
commponents:小型組件 主頁面也有不少小組件python
views:大型組件 好比主頁面的組件linux
router.js 路由配置 redis
APP.vue 整個項目的入口 數據庫
main.js 鏈接APP.vue的js文件 裏面Vue對象的參數全局均可以取到django
store Vuex 存全局的變量編程
package.json:裝了的依賴能在裏面看見。json
readme:裏面有些基本的運行命令
寫前端項目就是寫組件,而後和後端交互。
先後端分離:瀏覽器直接向前端服務器發送請求,從前端拿頁面,前端從後端拿數據,渲染在前端,而後返回給瀏覽器。
任何一個組件都是由三部分組成 :template script style
vue項目開發都是單頁面應用,在一個頁面跳轉,由數據驅動。
2、路飛學城項目設計
項目:路飛學城(在線學習的平臺)
1、背景
目的是作一個在線的學習平臺,提升學生的課程完成度
路飛學城:大目標是要取代線下班
2、系統架構
- 主站 - rest api - vue - 導師後臺 (stark) - django - stark - 管理後臺 (stark) - django - stark
3、人員和部門
- 後端開發(5人) - 主站(3) - 導師後臺(1) - 管理後臺(1) - 前端開發(1) - UI (1) - 測試(1) - 運維(部署:上線)(1) - 運營(推廣出去)(2) - 銷售 (2) - 導師 (2) - 產品經理 (1) - 人事 - 財務
4、需求分析
主站 - 課程 - 普通課程、學位課 - 普通課程:比較小的課程 - 學位課:從開始+項目+就業 - 分配一對一的導師 - 導師對你進行監管,督促你學習 - 保就業 - 若是你%50的時間學完了,退通常的學費,等。 - 課程列表、課程詳細 - 課程週期的不一樣訂價格 - 我的的課程中心 - 支付 - 銀聯- 支付寶 - 微信 - 優惠券策略(滿減(滿多少減多少),立減,打折) - 貝里:可直接抵現金 - 我的購物車 - 深科技 - 文章或者爬取的別人的文章(運營須要審覈)
- 深入有哪些功能?
- 點贊、評論、查看、收藏 - 登陸 、註冊 導師後臺 管理後臺
具體進一步談業務需求
a、課程: 業務相關: 一、學位課,若是你學的快;最多返指定金額的65% 二、做業作的好,會把額外的35%返給你 三、普通課程購買課程後,在個人訂單中去評價 四、購物車的數據沒有數據表。保存到redis裏面去了 兩大部分操做 #redis操做 在課程詳細頁面,選擇價格策略,點擊加入購物車,吧視頻和價格策略放到了redis中 在購物車頁面, 能夠對redis中保存的購買的視頻數據和價格數據能夠刪除,修改,添加,查看(刷新) 選中,去結算中心 #數據庫操做 #pip freeze > requirement.txt #生成文件 #pip install -r requirement.txt #下載全部的版本 在結算頁面: 優惠券 - 選擇單一的優惠券(通用、滿減、折扣) - 課程優惠券:綁定課程的優惠券 - 選擇全站的優惠券(通用、滿減、折扣) #單一的優惠券用完,再計算,看是否知足全站的通用卷 - 選擇貝里 - 選擇支付寶,點擊當即支付 - 在數據庫中生成一個訂單 這個訂單若是用了優惠券,優惠券狀態改成已使用 若是用了貝里,貝里的金額減小 若是取消訂單,優惠券纔不是使用狀態 在支付頁面,掃碼狀態爲已支付 在個人訂單中應該去數據庫中讀數據 在購物車或者結算中心的時候去redis裏面讀數據 課程列表和課程詳細等等等 若是購買課程 - 普通課程 - 學位課程 - 每一個模塊生成記錄(人和課程模塊的記錄) - 買完以後自動生成 - 開通模塊(後臺) - 導師跟進(導師) - 交做業(主站) b、深科技相關 來源 文章 收藏 通用評論表 c、購買支付流程 課程id和價格策略id 傳值的時候能夠傳兩個值 - 經過策略id找到買的那個課程 - 經過課程id 獲取全部的價格策略 處理請求 一、檢測課程是否上線,下線 二、經過課程id 獲取全部的價格策略,和傳過來的進行對比 三、檢測用戶提交的價格策略是否在全部的價格策略中 四、將購物的視頻添加到購物車(redis) - 同一個課程只能買一個,不容許一下加入兩個 吧數據放到redis中,那麼怎麼存? 一我的就有一個購物車。能夠經過用戶id來存 全部的購物車= { 1:{ 課程id1:{'prices':[],'price':9,'title':'python','img':'課程圖片'}, 課程id2:{'prices':[]} } } #若是看到課程已經在裏面了,就不在裏面添加了,這也就是用redis的緣由 class ShoppingCat(APIView): def post(): #點擊加入購物車保存數據到redis def get(): #查看購物車列表 def delete(): #刪除 def patch(): #局部更新 pass 五、去結算(先簡單的說一下) 買的全部的課程 課程1 價格策略 課程2 價格策略 課程3 價格策略 點擊了去結算 優惠券 貝里
5、表結構
課程相關的13張表
課程大類表:e.g 前端,後端 課程子類表:e.g python ,linux 普通課程表 學位課表 ##學位課能夠有以下好處 學位獎學金錶
##固然學位課和普通課程共有的 價格策略表 優惠券表
課程詳細表 課程章節表 課程目錄表 課程問答表 課程評價(先不討論)
課程大綱
## 老師表 contenttype contentType 能夠一下關聯兩張表,django本身提供了,不用本身建立
深科技相關的4張表
文章來源
文章資訊
收藏(既能收藏課程,也能收藏文章,能夠用contenttype)
評論(能夠用contenttype的形式也能夠用ForeignKey的形式)
用戶相關的兩張表
用戶信息表account
用戶認證表userauthtoken
- 若是用戶初次登陸,給用戶建立一個token,若是已經有token了,下次用戶訪問的時候直接帶上token,若是沒有token就說明沒有登陸,就沒有訪問其餘頁面的權限
購買支付相關的7張表
已報名課程表EnrolledCourse(誰購買了那個課程)
學位課報名表
已報名的學位課程表EnrolledDegreeCourse
優惠券發放、消費記錄
訂單表
訂單詳情
貝里交易記錄
其餘相關的6張表
課程評價
學位課程評價
學位課程的模塊學習進度
爲學生開通一個模塊
學生做業記錄及成績
學員跟進記錄
一、簡單表結構設計分析:
須要知道的知識點:
如今學位課和普通課程都有本身的價格策略和優惠券,如今是學位課已經有了本身的價格策略,那麼若是普通課程也要加價格策略,怎麼弄呢?
一下有三種方法:
方法一:再單首創建一個表
方法二:不用單首創建一個表,能夠多添加一個字段,其中的一個爲NULL。相比方法一省了一張表
方法三:能夠經過ContentType ,這個表裏面存的是應用的名字以及表名。可是在咱們makemigrations和migrate的時候django已經幫咱們建立好了,以下圖。就不用咱們本身建立了
這樣關聯的好處:能夠ForeignKey任何一張表。裏面的xid是關聯表的某一行數據,
這樣關聯之後,若是想在價格策略裏面在添加一行數據,怎麼添加呢?
有兩種方式:
方式一:手動插入
方式二:利用GenericForeignKey
from django.contrib.contenttypes.fields import GenericForeignKey
使用:
content_object = GenericForeignKey('content_type', 'object_id') #一下能夠查到兩個表的數據,自動插入到價格策略表裏了,
優惠券表也是如此。只是爲了查詢方便
另外補充一個GenericRelation
from django.contrib.contenttypes.fields import GenericRelation
GenericRelation:也是幫助作快速查詢的,就像反向關聯的releated_name=‘xx’。之後查找的時候通能夠經過點字段名的方式去查找
# 用於GenericForeignKey反向查詢, 不會生成表字段,切勿刪除 coupon = GenericRelation("Coupon") #也是幫助作快速查詢的,能夠直接查出全部的學位課的價格策略等
二、具體表結構設計以下:
課程相關的13張表格
1 from django.db import models 2 from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation 3 #GenericForeignKey有自動查找的功能,協助你快速作操做,沒有也能夠,本身手動查詢 4 #GenericRelation:也是幫助作快速查詢的,能夠直接查出全部的學位課的價格策略等 5 6 from django.contrib.contenttypes.models import ContentType 7 from django.db.models import Q 8 from django.utils.safestring import mark_safe 9 from django.db import models 10 import hashlib 11 12 class CourseCategory(models.Model): 13 """課程大類, e.g 前端 後端...""" 14 name = models.CharField(max_length=64, unique=True) 15 16 def __str__(self): 17 return "%s" % self.name 18 19 class Meta: 20 verbose_name = "課程大類" #單數 21 verbose_name_plural = "課程大類" #複數 22 23 class CourseSubCategory(models.Model): 24 """課程子類, e.g python linux """ 25 category = models.ForeignKey("CourseCategory",verbose_name='所屬類') 26 name = models.CharField(max_length=64, unique=True) 27 28 def __str__(self): 29 return "%s" % self.name 30 31 class Meta: 32 verbose_name = "課程子類" 33 verbose_name_plural = "課程子類" 34 35 class DegreeCourse(models.Model): 36 """學位課程""" 37 name = models.CharField(max_length=128, unique=True) 38 course_img = models.CharField(max_length=255, verbose_name="縮略圖") 39 brief = models.TextField(verbose_name="學位課程簡介", ) 40 total_scholarship = models.PositiveIntegerField(verbose_name="總獎學金(貝里)", default=40000) 41 mentor_compensation_bonus = models.PositiveIntegerField(verbose_name="本課程的導師輔導費用(貝里)", default=15000) 42 # 用於GenericForeignKey反向查詢, 不會生成表字段,切勿刪除 43 coupon = GenericRelation("Coupon") #也是幫助作快速查詢的,能夠直接查出全部的學位課的價格策略等 44 # 爲了計算學位獎學金 45 period = models.PositiveIntegerField(verbose_name="建議學習週期(days)", default=150) 46 prerequisite = models.TextField(verbose_name="課程先修要求", max_length=1024) 47 teachers = models.ManyToManyField("Teacher", verbose_name="課程講師") 48 # 用於GenericForeignKey反向查詢,不會生成表字段,切勿刪除 49 degreecourse_price_policy = GenericRelation("PricePolicy") 50 51 def __str__(self): 52 return self.name 53 54 class Course(models.Model): 55 """課程""" 56 name = models.CharField(max_length=128, unique=True) 57 course_img = models.CharField(max_length=255) 58 sub_category = models.ForeignKey("CourseSubCategory") 59 course_type_choices = ((0, '付費'), (1, 'VIP專享'), (2, '學位課程')) 60 course_type = models.SmallIntegerField(choices=course_type_choices) 61 degree_course = models.ForeignKey("DegreeCourse", blank=True, null=True, help_text="如果學位課程,此處關聯學位表") 62 brief = models.TextField(verbose_name="課程概述", max_length=2048) 63 level_choices = ((0, '初級'), (1, '中級'), (2, '高級')) 64 level = models.SmallIntegerField(choices=level_choices, default=1) 65 pub_date = models.DateField(verbose_name="發佈日期", blank=True, null=True) 66 period = models.PositiveIntegerField(verbose_name="建議學習週期(days)", default=7) 67 order = models.IntegerField("課程順序", help_text="從上一個課程數字日後排") 68 attachment_path = models.CharField(max_length=128, verbose_name="課件路徑", blank=True, null=True) 69 status_choices = ((0, '上線'), (1, '下線'), (2, '預上線')) 70 status = models.SmallIntegerField(choices=status_choices, default=0) 71 template_id = models.SmallIntegerField("前端模板id", default=1) 72 coupon = GenericRelation("Coupon") 73 # 用於GenericForeignKey反向查詢,不會生成表字段,切勿刪除 74 price_policy = GenericRelation("PricePolicy") 75 76 def __str__(self): 77 return "%s(%s)" % (self.name, self.get_course_type_display()) 78 79 def save(self, *args, **kwargs): 80 if self.course_type == 2: 81 if not self.degree_course: 82 raise ValueError("學位課程必須關聯對應的學位表") 83 super(Course, self).save(*args, **kwargs) 84 85 class CourseDetail(models.Model): 86 """課程詳情頁內容""" 87 course = models.OneToOneField("Course") 88 hours = models.IntegerField("課時") 89 course_slogan = models.CharField(max_length=125, blank=True, null=True) 90 video_brief_link = models.CharField(verbose_name='課程介紹', max_length=255, blank=True, null=True) 91 why_study = models.TextField(verbose_name="爲何學習這門課程") 92 what_to_study_brief = models.TextField(verbose_name="我將學到哪些內容") 93 career_improvement = models.TextField(verbose_name="此項目如何有助於個人職業生涯") 94 prerequisite = models.TextField(verbose_name="課程先修要求", max_length=1024) 95 recommend_courses = models.ManyToManyField("Course", related_name="recommend_by", blank=True) 96 teachers = models.ManyToManyField("Teacher", verbose_name="課程講師") 97 98 def __str__(self): 99 return "%s" % self.course 100 101 class OftenAskedQuestion(models.Model): 102 """常見問題""" 103 content_type = models.ForeignKey(ContentType, 104 limit_choices_to={'model__contains': 'course'}) # 關聯course or degree_course 105 object_id = models.PositiveIntegerField() 106 content_object = GenericForeignKey('content_type', 'object_id') 107 108 question = models.CharField(max_length=255) 109 answer = models.TextField(max_length=1024) 110 111 def __str__(self): 112 return "%s-%s" % (self.content_object, self.question) 113 114 class Meta: 115 unique_together = ('content_type', 'object_id', 'question') 116 117 class CourseOutline(models.Model): 118 """課程大綱""" 119 course_detail = models.ForeignKey("CourseDetail") 120 title = models.CharField(max_length=128) 121 # 前端顯示順序 122 order = models.PositiveSmallIntegerField(default=1) 123 124 content = models.TextField("內容", max_length=2048) 125 126 def __str__(self): 127 return "%s" % self.title 128 129 class Meta: 130 unique_together = ('course_detail', 'title') 131 132 class CourseChapter(models.Model): 133 """課程章節""" 134 course = models.ForeignKey("Course", related_name='coursechapters') 135 chapter = models.SmallIntegerField(verbose_name="第幾章", default=1) 136 name = models.CharField(max_length=128) 137 summary = models.TextField(verbose_name="章節介紹", blank=True, null=True) 138 pub_date = models.DateField(verbose_name="發佈日期", auto_now_add=True) 139 140 class Meta: 141 unique_together = ("course", 'chapter') 142 143 def __str__(self): 144 return "%s:(第%s章)%s" % (self.course, self.chapter, self.name) 145 146 class Teacher(models.Model): 147 """講師、導師表""" 148 name = models.CharField(max_length=32) 149 role_choices = ((0, '講師'), (1, '導師')) 150 role = models.SmallIntegerField(choices=role_choices, default=0) 151 title = models.CharField(max_length=64, verbose_name="職位、職稱") 152 signature = models.CharField(max_length=255, help_text="導師簽名", blank=True, null=True) 153 image = models.CharField(max_length=128) 154 brief = models.TextField(max_length=1024) 155 156 def __str__(self): 157 return self.name 158 159 class PricePolicy(models.Model): 160 """價格與有課程效期表""" 161 content_type = models.ForeignKey(ContentType) # 關聯course or degree_course 162 object_id = models.PositiveIntegerField() 163 content_object = GenericForeignKey('content_type', 'object_id') 164 165 # course = models.ForeignKey("Course") 166 valid_period_choices = ((1, '1天'), (3, '3天'), 167 (7, '1周'), (14, '2周'), 168 (30, '1個月'), 169 (60, '2個月'), 170 (90, '3個月'), 171 (180, '6個月'), (210, '12個月'), 172 (540, '18個月'), (720, '24個月'), 173 ) 174 valid_period = models.SmallIntegerField(choices=valid_period_choices) 175 price = models.FloatField() 176 177 class Meta: 178 unique_together = ("content_type", 'object_id', "valid_period") 179 180 def __str__(self): 181 return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price) 182 183 class CourseSection(models.Model): 184 """課時目錄""" 185 chapter = models.ForeignKey("CourseChapter", related_name='coursesections') 186 name = models.CharField(max_length=128) 187 order = models.PositiveSmallIntegerField(verbose_name="課時排序", help_text="建議每一個課時之間空1至2個值,以備後續插入課時") 188 section_type_choices = ((0, '文檔'), (1, '練習'), (2, '視頻')) 189 section_type = models.SmallIntegerField(default=2, choices=section_type_choices) 190 191 192 section_link = models.CharField(max_length=255, blank=True, null=True, help_text="如果video,填vid,如果文檔,填link") 193 # vid:cc視頻,惟一標識:sdfsgdfgdgfhgfh 194 video_time = models.CharField(verbose_name="視頻時長", blank=True, null=True, max_length=32) # 僅在前端展現使用 195 pub_date = models.DateTimeField(verbose_name="發佈時間", auto_now_add=True) 196 free_trail = models.BooleanField("是否可試看", default=False) 197 198 199 class Meta: 200 unique_together = ('chapter', 'section_link') 201 202 203 def __str__(self): 204 return "%s-%s" % (self.chapter, self.name) 205 206 class Coupon(models.Model): 207 """優惠券生成規則""" 208 name = models.CharField(max_length=64, verbose_name="活動名稱") 209 brief = models.TextField(blank=True, null=True, verbose_name="優惠券介紹") 210 coupon_type_choices = ((0, '通用券'), (1, '滿減券'), (2, '折扣券')) 211 coupon_type = models.SmallIntegerField(choices=coupon_type_choices, default=0, verbose_name="券類型") 212 213 money_equivalent_value = models.IntegerField(verbose_name="等值貨幣") 214 off_percent = models.PositiveSmallIntegerField("折扣百分比", help_text="只針對折扣券,例7.9折,寫79", blank=True, null=True) 215 minimum_consume = models.PositiveIntegerField("最低消費", default=0, help_text="僅在滿減券時填寫此字段") 216 217 content_type = models.ForeignKey(ContentType, blank=True, null=True) 218 object_id = models.PositiveIntegerField("綁定課程", blank=True, null=True, help_text="能夠把優惠券跟課程綁定") 219 content_object = GenericForeignKey('content_type', 'object_id') 220 221 quantity = models.PositiveIntegerField("數量(張)", default=1) 222 open_date = models.DateField("優惠券領取開始時間") 223 close_date = models.DateField("優惠券領取結束時間") 224 valid_begin_date = models.DateField(verbose_name="有效期開始時間", blank=True, null=True) 225 valid_end_date = models.DateField(verbose_name="有效結束時間", blank=True, null=True) 226 coupon_valid_days = models.PositiveIntegerField(verbose_name="優惠券有效期(天)", blank=True, null=True, 227 help_text="自券被領時開始算起") 228 date = models.DateTimeField(auto_now_add=True) 229 230 def __str__(self): 231 return "%s(%s)" % (self.get_coupon_type_display(), self.name) 232 233 def save(self, *args, **kwargs): 234 if not self.coupon_valid_days or (self.valid_begin_date and self.valid_end_date): 235 if self.valid_begin_date and self.valid_end_date: 236 if self.valid_end_date <= self.valid_begin_date: 237 raise ValueError("valid_end_date 有效期結束日期必須晚於 valid_begin_date ") 238 if self.coupon_valid_days == 0: 239 raise ValueError("coupon_valid_days 有效期不能爲0") 240 if self.close_date < self.open_date: 241 raise ValueError("close_date 優惠券領取結束時間必須晚於 open_date優惠券領取開始時間 ") 242 243 super(Coupon, self).save(*args, **kwargs) 244 245 課程相關的13張表
深科技相關
1 # ######################## 深科技相關 ######################## 2 3 class ArticleSource(models.Model): 4 """文章來源""" 5 name = models.CharField(max_length=64, unique=True) 6 7 def __str__(self): 8 return self.name 9 10 11 class Article(models.Model): 12 """文章資訊""" 13 title = models.CharField(max_length=255, unique=True, db_index=True, verbose_name="標題") 14 source = models.ForeignKey("ArticleSource", verbose_name="來源") 15 article_type_choices = ((0, '資訊'), (1, '視頻')) 16 article_type = models.SmallIntegerField(choices=article_type_choices, default=0) 17 brief = models.TextField(max_length=512, verbose_name="摘要") 18 head_img = models.CharField(max_length=255) 19 content = models.TextField(verbose_name="文章正文") 20 pub_date = models.DateTimeField(verbose_name="上架日期") 21 offline_date = models.DateTimeField(verbose_name="下架日期") 22 status_choices = ((0, '在線'), (1, '下線')) 23 status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="狀態") 24 order = models.SmallIntegerField(default=0, verbose_name="權重", help_text="文章想置頂,能夠把數字調大,不要超過1000") 25 vid = models.CharField(max_length=128, verbose_name="視頻VID", help_text="文章類型是視頻, 則須要添加視頻VID", blank=True, null=True) 26 comment_num = models.SmallIntegerField(default=0, verbose_name="評論數") 27 agree_num = models.SmallIntegerField(default=0, verbose_name="點贊數") 28 view_num = models.SmallIntegerField(default=0, verbose_name="觀看數") 29 collect_num = models.SmallIntegerField(default=0, verbose_name="收藏數") 30 31 tags = models.ManyToManyField("Tags", blank=True, verbose_name="標籤") 32 date = models.DateTimeField(auto_now_add=True, verbose_name="建立日期") 33 34 position_choices = ((0, '信息流'), (1, 'banner大圖'), (2, 'banner小圖')) 35 position = models.SmallIntegerField(choices=position_choices, default=0, verbose_name="位置") 36 comment = GenericRelation("Comment") # 用於GenericForeignKey反向查詢, 不會生成表字段,切勿刪除,若有疑問請聯繫老村長 37 38 def __str__(self): 39 return "%s-%s" % (self.source, self.title) 40 41 42 class Collection(models.Model): 43 """收藏""" 44 content_type = models.ForeignKey(ContentType) 45 object_id = models.PositiveIntegerField() 46 content_object = GenericForeignKey('content_type', 'object_id') 47 48 account = models.ForeignKey("Account") 49 date = models.DateTimeField(auto_now_add=True) 50 51 class Meta: 52 unique_together = ('content_type', 'object_id', 'account') 53 54 55 # 深科技評論和視頻評論 56 class Comment(models.Model): 57 """通用的評論表: 課程評論 """ 58 content_type = models.ForeignKey(ContentType, blank=True, null=True, verbose_name="類型") 59 object_id = models.PositiveIntegerField(blank=True, null=True) 60 content_object = GenericForeignKey('content_type', 'object_id') 61 62 p_node = models.ForeignKey("self", blank=True, null=True, verbose_name="父級評論") 63 content = models.TextField(max_length=1024) 64 account = models.ForeignKey("Account", verbose_name="會員名") 65 disagree_number = models.IntegerField(default=0, verbose_name="踩") 66 agree_number = models.IntegerField(default=0, verbose_name="贊同數") 67 date = models.DateTimeField(auto_now_add=True) 68 69 def __str__(self): 70 return self.content 71 72 深科技相關
購買課程相關的8張表
1 # ######################## 購買課程相關 ######################## 2 3 class EnrolledCourse(models.Model): 4 """已報名課程,不包括學位課程""" 5 account = models.ForeignKey("Account") 6 course = models.ForeignKey("Course", limit_choices_to=~Q(course_type=2)) 7 enrolled_date = models.DateTimeField(auto_now_add=True) 8 valid_begin_date = models.DateField(verbose_name="有效期開始自") 9 valid_end_date = models.DateField(verbose_name="有效期結束至") 10 status_choices = ((0, '已開通'), (1, '已過時')) 11 status = models.SmallIntegerField(choices=status_choices, default=0) 12 order_detail = models.OneToOneField("OrderDetail") # 使訂單購買後支持 課程評價 13 14 # order = models.ForeignKey("Order",blank=True,null=True) 15 16 def __str__(self): 17 return "%s:%s" % (self.account, self.course) 18 19 20 class DegreeRegistrationForm(models.Model): 21 """學位課程報名表""" 22 enrolled_degree = models.OneToOneField("EnrolledDegreeCourse") 23 current_company = models.CharField(max_length=64, ) 24 current_position = models.CharField(max_length=64, ) 25 current_salary = models.IntegerField() 26 work_experience_choices = ( 27 (0, "應屆生"), 28 (1, "1年"), 29 (2, "2年"), 30 (3, "3年"), 31 (4, "4年"), 32 (5, "5年"), 33 (6, "6年"), 34 (7, "7年"), 35 (8, "8年"), 36 (9, "9年"), 37 (10, "10年"), 38 (11, "超過10年"), 39 ) 40 work_experience = models.IntegerField() 41 open_module = models.BooleanField("是否開通第1模塊", default=True) 42 stu_specified_mentor = models.CharField("學員自行指定的導師名", max_length=32, blank=True, null=True) 43 study_plan_choices = ((0, "1-2小時/天"), 44 (1, "2-3小時/天"), 45 (2, "3-5小時/天"), 46 (3, "5小時+/天"), 47 ) 48 study_plan = models.SmallIntegerField(choices=study_plan_choices, default=1) 49 why_take_this_course = models.TextField("報此課程緣由", max_length=1024) 50 why_choose_us = models.TextField("爲什麼選路飛", max_length=1024) 51 your_expectation = models.TextField("你的期待", max_length=1024) 52 memo = models.CharField(max_length=255, blank=True, null=True) 53 54 def __str__(self): 55 return "%s" % self.enrolled_degree 56 57 58 class EnrolledDegreeCourse(models.Model): 59 """已報名的學位課程""" 60 account = models.ForeignKey("Account") 61 degree_course = models.ForeignKey("DegreeCourse") 62 enrolled_date = models.DateTimeField(auto_now_add=True) 63 valid_begin_date = models.DateField(verbose_name="有效期開始自", blank=True, null=True) # 開通第一個模塊時,再添加課程有效期,2年 64 valid_end_date = models.DateField(verbose_name="有效期結束至", blank=True, null=True) 65 status_choices = ( 66 (0, '在學中'), 67 (1, '休學中'), 68 (2, '已畢業'), 69 (3, '超時結業'), 70 (4, '未開始'), 71 # (3, '其它'), 72 ) 73 study_status = models.SmallIntegerField(choices=status_choices, default=0) 74 mentor = models.ForeignKey("Account", verbose_name="導師", related_name='my_students', 75 blank=True, null=True, limit_choices_to={'role': 1}) 76 mentor_fee_balance = models.PositiveIntegerField("導師費用餘額", help_text="這個學員的導師費用,每有懲罰,需在此字段同時扣除") 77 order_detail = models.OneToOneField("OrderDetail") # 使訂單購買後支持填寫報名表 78 79 def __str__(self): 80 return "%s:%s" % (self.account, self.degree_course) 81 82 class Meta: 83 unique_together = ('account', 'degree_course') 84 85 86 class Coupon(models.Model): 87 """優惠券生成規則""" 88 name = models.CharField(max_length=64, verbose_name="活動名稱") 89 brief = models.TextField(blank=True, null=True, verbose_name="優惠券介紹") 90 coupon_type_choices = ((0, '通用券'), (1, '滿減券'), (2, '折扣券')) 91 coupon_type = models.SmallIntegerField(choices=coupon_type_choices, default=0, verbose_name="券類型") 92 93 money_equivalent_value = models.IntegerField(verbose_name="等值貨幣") 94 off_percent = models.PositiveSmallIntegerField("折扣百分比", help_text="只針對折扣券,例7.9折,寫79", blank=True, null=True) 95 minimum_consume = models.PositiveIntegerField("最低消費", default=0, help_text="僅在滿減券時填寫此字段") 96 97 content_type = models.ForeignKey(ContentType, blank=True, null=True) 98 object_id = models.PositiveIntegerField("綁定課程", blank=True, null=True, help_text="能夠把優惠券跟課程綁定") 99 content_object = GenericForeignKey('content_type', 'object_id') 100 101 quantity = models.PositiveIntegerField("數量(張)", default=1) 102 open_date = models.DateField("優惠券領取開始時間") 103 close_date = models.DateField("優惠券領取結束時間") 104 valid_begin_date = models.DateField(verbose_name="有效期開始時間", blank=True, null=True) 105 valid_end_date = models.DateField(verbose_name="有效結束時間", blank=True, null=True) 106 coupon_valid_days = models.PositiveIntegerField(verbose_name="優惠券有效期(天)", blank=True, null=True, 107 help_text="自券被領時開始算起") 108 date = models.DateTimeField(auto_now_add=True) 109 110 def __str__(self): 111 return "%s(%s)" % (self.get_coupon_type_display(), self.name) 112 113 def save(self, *args, **kwargs): 114 if not self.coupon_valid_days or (self.valid_begin_date and self.valid_end_date): 115 if self.valid_begin_date and self.valid_end_date: 116 if self.valid_end_date <= self.valid_begin_date: 117 raise ValueError("valid_end_date 有效期結束日期必須晚於 valid_begin_date ") 118 if self.coupon_valid_days == 0: 119 raise ValueError("coupon_valid_days 有效期不能爲0") 120 if self.close_date < self.open_date: 121 raise ValueError("close_date 優惠券領取結束時間必須晚於 open_date優惠券領取開始時間 ") 122 123 super(Coupon, self).save(*args, **kwargs) 124 125 126 class CouponRecord(models.Model): 127 """優惠券發放、消費紀錄""" 128 coupon = models.ForeignKey("Coupon") 129 #number = models.CharField(max_length=64, unique=True) 130 account = models.ForeignKey("Account", verbose_name="擁有者") 131 status_choices = ((0, '未使用'), (1, '已使用'), (2, '已過時'),) 132 status = models.SmallIntegerField(choices=status_choices, default=0) 133 get_time = models.DateTimeField(verbose_name="領取時間", help_text="用戶領取時間") 134 used_time = models.DateTimeField(blank=True, null=True, verbose_name="使用時間") 135 order = models.ForeignKey("Order", blank=True, null=True, verbose_name="關聯訂單") # 一個訂單能夠有多個優惠券 136 137 138 class Order(models.Model): 139 """訂單""" 140 payment_type_choices = ((0, '微信'), (1, '支付寶'), (2, '優惠碼'), (3, '貝里')) 141 payment_type = models.SmallIntegerField(choices=payment_type_choices) 142 payment_number = models.CharField(max_length=128, verbose_name="支付第3方訂單號", null=True, blank=True) 143 order_number = models.CharField(max_length=128, verbose_name="訂單號", unique=True) # 考慮到訂單合併支付的問題 144 account = models.ForeignKey("Account") 145 actual_amount = models.FloatField(verbose_name="實付金額") 146 147 status_choices = ((0, '交易成功'), (1, '待支付'), (2, '退費申請中'), (3, '已退費'), (4, '主動取消'), (5, '超時取消')) 148 status = models.SmallIntegerField(choices=status_choices, verbose_name="狀態") 149 date = models.DateTimeField(auto_now_add=True, verbose_name="訂單生成時間") 150 pay_time = models.DateTimeField(blank=True, null=True, verbose_name="付款時間") 151 cancel_time = models.DateTimeField(blank=True, null=True, verbose_name="訂單取消時間") 152 153 def __str__(self): 154 return "%s" % self.order_number 155 156 157 class OrderDetail(models.Model): 158 """訂單詳情""" 159 order = models.ForeignKey("Order") 160 161 content_type = models.ForeignKey(ContentType) # 可關聯普通課程或學位 162 object_id = models.PositiveIntegerField() 163 content_object = GenericForeignKey('content_type', 'object_id') 164 165 original_price = models.FloatField("課程原價") 166 price = models.FloatField("折後價格") 167 content = models.CharField(max_length=255, blank=True, null=True) # ? 168 valid_period_display = models.CharField("有效期顯示", max_length=32) # 在訂單頁顯示 169 valid_period = models.PositiveIntegerField("有效期(days)") # 課程有效期 170 memo = models.CharField(max_length=255, blank=True, null=True) 171 172 # def __str__(self): 173 # return "%s - %s - %s" % (self.order, self.content_type, self.price) 174 175 class Meta: 176 # unique_together = ("order", 'course') 177 unique_together = ("order", 'content_type', 'object_id') 178 179 180 class TransactionRecord(models.Model): 181 """貝里交易紀錄""" 182 account = models.ForeignKey("Account") 183 amount = models.IntegerField("金額") 184 balance = models.IntegerField("帳戶餘額") 185 transaction_type_choices = ((0, '收入'), (1, '支出'), (2, '退款'), (3, "提現")) # 2 爲了處理 訂單過時未支付時,鎖按期貝里的回退 186 transaction_type = models.SmallIntegerField(choices=transaction_type_choices) 187 188 content_type = models.ForeignKey(ContentType, blank=True, null=True) 189 object_id = models.PositiveIntegerField(blank=True, null=True, verbose_name="關聯對象") 190 content_object = GenericForeignKey('content_type', 'object_id') 191 192 transaction_number = models.CharField(unique=True, verbose_name="流水號", max_length=128) 193 date = models.DateTimeField(auto_now_add=True) 194 memo = models.CharField(max_length=128, blank=True, null=True) 195 196 def __str__(self): 197 return "%s" % self.transaction_number 198 199 購買課程相關的8張表
學位課優惠相關的的表
1 class Homework(models.Model): 2 chapter = models.ForeignKey("CourseChapter") 3 title = models.CharField(max_length=128, verbose_name="做業題目") 4 order = models.PositiveSmallIntegerField("做業順序", help_text="同一課程的每一個做業以前的order值間隔1-2個數") 5 homework_type_choices = ((0, '做業'), (1, '模塊通關考覈')) 6 homework_type = models.SmallIntegerField(choices=homework_type_choices, default=0) 7 requirement = models.TextField(max_length=1024, verbose_name="做業需求") 8 threshold = models.TextField(max_length=1024, verbose_name="踩分點") 9 recommend_period = models.PositiveSmallIntegerField("推薦完成周期(天)", default=7) 10 scholarship_value = models.PositiveSmallIntegerField("爲該做業分配的獎學金(貝里)") 11 note = models.TextField(blank=True, null=True) 12 enabled = models.BooleanField(default=True, help_text="本做業若是後期不須要了,不想讓學員看到,能夠設置爲False") 13 14 class Meta: 15 unique_together = ("chapter", "title") 16 17 def __str__(self): 18 return "%s - %s" % (self.chapter, self.title) 19 20 21 class Teacher(models.Model): 22 """講師、導師表""" 23 name = models.CharField(max_length=32) 24 role_choices = ((0, '講師'), (1, '導師')) 25 role = models.SmallIntegerField(choices=role_choices, default=0) 26 title = models.CharField(max_length=64, verbose_name="職位、職稱") 27 signature = models.CharField(max_length=255, help_text="導師簽名", blank=True, null=True) 28 image = models.CharField(max_length=128) 29 brief = models.TextField(max_length=1024) 30 31 def __str__(self): 32 return self.name 33 34 35 # 普通課購買課程後,個人訂單中去評價。 36 class CourseReview(models.Model): 37 """課程評價""" 38 enrolled_course = models.OneToOneField("EnrolledCourse") 39 about_teacher = models.FloatField(default=0, verbose_name="講師講解是否清晰") 40 about_video = models.FloatField(default=0, verbose_name="內容實用") 41 about_course = models.FloatField(default=0, verbose_name="課程內容通俗易懂") 42 review = models.TextField(max_length=1024, verbose_name="評價") 43 disagree_number = models.IntegerField(default=0, verbose_name="踩") 44 agree_number = models.IntegerField(default=0, verbose_name="贊同數") 45 tags = models.ManyToManyField("Tags", blank=True, verbose_name="標籤") 46 date = models.DateTimeField(auto_now_add=True, verbose_name="評價日期") 47 is_recommend = models.BooleanField("熱評推薦", default=False) 48 hide = models.BooleanField("不在前端頁面顯示此條評價", default=False) 49 50 def __str__(self): 51 return "%s-%s" % (self.enrolled_course.course, self.review) 52 53 54 # 學位課購買課程後,個人訂單中去天報名表,而後就編程去學習(之後去評價)。 55 class DegreeCourseReview(models.Model): 56 """學位課程評價 57 爲了之後能夠定製單獨的評價內容,因此不與普通課程的評價混在一塊兒,單獨建表 58 """ 59 enrolled_course = models.ForeignKey("EnrolledDegreeCourse") 60 course = models.ForeignKey("Course", verbose_name="評價學位模塊", blank=True, null=True, 61 help_text="不填寫即表明評價整個學位課程", limit_choices_to={'course_type': 2}) 62 about_teacher = models.FloatField(default=0, verbose_name="講師講解是否清晰") 63 about_video = models.FloatField(default=0, verbose_name="視頻質量") 64 about_course = models.FloatField(default=0, verbose_name="課程") 65 review = models.TextField(max_length=1024, verbose_name="評價") 66 disagree_number = models.IntegerField(default=0, verbose_name="踩") 67 agree_number = models.IntegerField(default=0, verbose_name="贊同數") 68 tags = models.ManyToManyField("Tags", blank=True, verbose_name="標籤") 69 date = models.DateTimeField(auto_now_add=True, verbose_name="評價日期") 70 is_recommend = models.BooleanField("熱評推薦", default=False) 71 hide = models.BooleanField("不在前端頁面顯示此條評價", default=False) 72 73 def __str__(self): 74 return "%s-%s" % (self.enrolled_course, self.review) 75 76 77 78 # 購買學位課後,爲每一個學生每一個模塊會馬上生成一條學習紀錄(未開通) 79 class StudyRecord(models.Model): 80 """學位課程的模塊學習進度 81 報名學位課程後,每一個模塊會馬上生成一條學習紀錄 82 """ 83 enrolled_degree_course = models.ForeignKey("EnrolledDegreeCourse") 84 course_module = models.ForeignKey("Course", verbose_name="學位模塊", limit_choices_to={'course_type': 2}) 85 open_date = models.DateField(blank=True, null=True, verbose_name="開通日期") 86 end_date = models.DateField(blank=True, null=True, verbose_name="完成日期") 87 status_choices = ((2, '在學'), (1, '未開通'), (0, '已完成')) 88 status = models.SmallIntegerField(choices=status_choices, default=1) 89 90 class Meta: 91 unique_together = ('enrolled_degree_course', 'course_module') 92 93 def __str__(self): 94 return '%s-%s' % (self.enrolled_degree_course, self.course_module) 95 96 def save(self, *args, **kwargs): 97 if self.course_module.degree_course_id != self.enrolled_degree_course.degree_course_id: 98 raise ValueError("學員要開通的模塊必須與其報名的學位課程一致!") 99 100 super(StudyRecord, self).save(*args, **kwargs) 101 102 103 # 爲學生開通一個模塊 104 class CourseSchedule(models.Model): 105 """課程進度計劃表,針對學位課程,每開通一個模塊,就爲這個學員生成這個模塊的推薦學習計劃表,後面的獎懲均按此表進行""" 106 study_record = models.ForeignKey("StudyRecord") 107 homework = models.ForeignKey("Homework") 108 recommend_date = models.DateField("推薦交做業日期") 109 110 def __str__(self): 111 return "%s - %s - %s " % (self.study_record, self.homework, self.recommend_date) 112 113 class Meta: 114 unique_together = ('study_record', 'homework') 115 116 117 # 學生交做業 118 class HomeworkRecord(models.Model): 119 """學員做業記錄及成績""" 120 homework = models.ForeignKey("Homework") 121 student = models.ForeignKey("EnrolledDegreeCourse", verbose_name="學生") 122 score_choices = ( 123 (100, 'A+'), 124 (90, 'A'), 125 (85, 'B+'), 126 (80, 'B'), 127 (70, 'B-'), 128 (60, 'C+'), 129 (50, 'C'), 130 (40, 'C-'), 131 (-1, 'D'), 132 (0, 'N/A'), 133 (-100, 'COPY'), 134 ) 135 score = models.SmallIntegerField(verbose_name="分數", choices=score_choices, null=True, blank=True) 136 mentor = models.ForeignKey("Account", related_name="my_stu_homework_record", limit_choices_to={'role': 1}, 137 verbose_name="導師") 138 mentor_comment = models.TextField(verbose_name="導師批註", blank=True, null=True) # 導師 139 status_choice = ( 140 (0, '待批改'), 141 (1, '已經過'), 142 (2, '不合格'), 143 ) 144 status = models.SmallIntegerField(verbose_name='做業狀態', choices=status_choice, default=0) 145 146 submit_num = models.SmallIntegerField(verbose_name='提交次數', default=0) 147 correct_date = models.DateTimeField('備註日期', blank=True, null=True) 148 note = models.TextField(blank=True, null=True) 149 date = models.DateTimeField("做業提交日期", auto_now_add=True) 150 151 check_date = models.DateTimeField("批改日期", null=True, blank=True) 152 153 update_time = models.DateTimeField(auto_now=True, verbose_name="提交日期") 154 155 # homework_path = models.CharField(verbose_name='做業路徑', max_length=256,blank=True,null=True) 做業路徑能夠動態拿到,不必存 156 157 reward_choice = ( 158 (0, '新提交'), 159 (1, '按時提交'), 160 (2, '未按時提交'), 161 (3, '成績已獎勵'), 162 (4, '成績已處罰'), 163 (5, '未做按時檢測'), 164 ) 165 reward_status = models.SmallIntegerField(verbose_name='做業記錄獎懲狀態', default=0) 166 167 def __str__(self): 168 return "%s %s" % (self.homework, self.student) 169 170 class Meta: 171 unique_together = ("homework", "student") 172 173 174 # 導師跟進記錄 175 class StuFollowUpRecord(models.Model): 176 """學員跟進記錄""" 177 enrolled_degree_course = models.ForeignKey("EnrolledDegreeCourse", verbose_name="學生") 178 mentor = models.ForeignKey("Account", related_name='mentor', limit_choices_to={'role': 1}, verbose_name="導師") 179 followup_tool_choices = ((0, 'QQ'), (1, '微信'), (2, '電話'), (3, '系統通知')) 180 followup_tool = models.SmallIntegerField(choices=followup_tool_choices, default=1) 181 record = models.TextField(verbose_name="跟進記錄") 182 attachment_path = models.CharField(max_length=128, blank=True, null=True, verbose_name="附件路徑", help_text="跟進記錄的截圖等") 183 date = models.DateTimeField(auto_now_add=True) 184 185 def __str__(self): 186 return "%s --%s --%s" % (self.enrolled_degree_course, self.record, self.date) 187 188 學位課優惠相關的表