本節內容
業務痛點分析
項目需求討論
使用場景分析
表結構設計
業務痛點分析
我2013年剛加入老男孩教育的時候,學校就一間教室,2個招生老師,招了學生后,招生老師就在自己的excel表里記錄一下,每月算工資時,就按這個表來統計招生提成, 后來學校大了點,教室變成了3間,招生老師變成了4個人,招的學生也開始多了起來,不過大家依然是招了學生就紀錄在自己的excel里,但問題開始出現了,我們的招生多是通過網絡qq聊天在線咨詢,好多客戶需要聊很久才能轉化成學員,經常會出現一個客戶跟一個招生老師聊過后,過了一段時間卻在另一個招生老師那報名了。 於是爭執就出現了,A銷售說這個人是先找我咨詢的,我幫他回答了大多數問題,報名提成卻算成B的,不公平。B銷售也會講,這個客戶找他咨詢時並未說自己之前跟其它銷售聊過呀,所以對B來講,這就是個新客戶呀,並且是在B這報的名, 憑什么要分提成給A呀。為了解決這個問題,於是想出一個辦法,搞了一個機器做共享服務器,共享服務器上搞了個統一的客戶信息excel表,大家每人聊過的客戶都在這個表里紀錄, 這樣每個人錄入前,先在表格里全局查一下,這個客戶的qq號是不是已經在表里了,這樣就能避免沖突了。 但用過共享文件的應該都遇到過一個問題就是,為保證數據一致性,同一時間系統只允許一個用戶修改數據, 但我們的每個招生老師一上班,就會打開這個共享文件,隨時聊的學生,隨時會錄入到表里。但這個限制使的大家,只要一有人錄入信息,就得要求其它銷售人員都把文件先關閉,錄入信息后其它人才能再用,這搞的大家很難受。 所以銷售人員經常讓我幫開發個系統,可以解決一些類似這樣的問題。
另外, 我們在講課時, 為了保證和檢驗學員的學習效果, 每節課講完時都會給學生部置一個作業,要求他必須在下節上課前完成並提交作業,老師會給學員統一批作業,作業成績也紀錄在excel表中,就像下圖一樣。每個老師維護自己班級的作業,校長如果想看各個班級的成績,還要跟每個老師要學員成績表,很不方便, 當時校長就跟我講,學員的成績\出勤情況等要是也能統一管理就好了。

於是我心里也一直紀着這個事,想幫學校開發一個學員開發一個類似CRM(客戶關系管理軟件)的系統,集銷售管理\學員管理等功能於一體。但平常要上班,周未還要講課,一直沒時間,終於有一次,我要去美帝度假,飛機要飛13個小時才到紐約,在飛機上突然想,反正也是沒事干, 不如就開發這個東西吧, 於是一路未眠,狂寫了近千行代碼,飛機的上的美女空乘都心疼的多給我倒了2杯咖啡,哈哈,下飛機時,已是兩眼痛紅,不過,這個學員管理系統的雛形也做出來了,接下來幾天在紐約又完善了下細節,於是就開始上線讓大家用了。到現在,這個系統在公司已經用了一年多了,大家每天都在使用,之前的痛點都解決了,特別是銷售人員, 工作已經離不開這個系統了,自己做的東西幫別人解決具體問題,心里還是蠻開森的!
個人覺得這個學員管理系統的挺適合新手練習的,難度適中,用戶的知識點也比較綜合,所以把學校里的系統簡化了一下,提練成了一個教學項目,下面我們就一起來做一個嘍。
噢,對了,最后說一下這個項目涉及到的知識點,請確保你以充分掌握了下面所列知識點再學習此項目噢!
-
Django
-
JQuery
-
BootStrap
-
Ajax
-
HTMS\CSS
項目需求討論
首先給我們的項目起個名字吧,這個系統要同時支持銷售管理\學員管理\講師管理等功能,功能比較雜,不能稱之為嚴格意上的CRM,因為CRM一般只包括銷售管理,but anyway, who cares,我們就叫它”老男孩crm管理系統”吧,
起好了名字,開始動手寫之前, 肯定要把需求想清楚,需求想不清楚就開始寫的話,等於給自己挖坑,你肯定不想出現寫了5千行代碼后,突然發現,需求搞錯了,還要重新推到重來的事情吧。所以,現在靜下心,把需求想明白,畫好思維導圖,跟同事多討論應用場景,做了各方面論證后,再開始動工噢。
我們的系統的用戶分3種,銷售\學生\講師,這3個角色關注的事情是不同的, 銷售只關注招了多少學員,講師關注自己管理的班級學習成績怎樣,學員只關注自己的學習成績。 因此在想需求時,你要從每個角色出發,看他關心的是什么, 於是我畫出了這個思維導圖

根據思維導圖,我們總結出以下具體需求:
- 把用戶分為銷售\學員\講師3種角色,每個角色關心的事情不同,所以有要不同的用戶視圖,即銷售人員登陸后只需要看他與他工作相關的就可以,講師關心的事情不需要在銷售視圖里顯示
- 銷售人員可以錄入客戶信息,和后續跟進信息,因為一個客戶可能要跟進好幾次才會報名。 可以多種條件過濾查詢用戶,可以查看自己的銷售業績報表
- 學員主要2個功能,查詢成績\提交作業
- 講師的主要功能是管理班級\ 批作業\上課點名
- 雖然現在只有一個校區,但要考慮到以后的擴展,以后全國可能有好多個校區,不同校區之間的數據應該是隔離的
- 這個系統里存放着大量的客戶信息\學員數據等,都是公司的機密信息,設計系統時就要考慮到權限問題,不同的角色要有不同的權限,同一角色的不同用戶也要允許有不同的權限
使用場景分析
為了更加理清我們的項目開發需求,在動手寫代碼前,建議再有一個業務場景分析的步驟,即從用戶角度寫出你使用這個項目的具體場景,我們這里分為銷售、講師、學員3個角色,我分別給每個角色列出了幾個使用場景:
一. 銷售:
- 銷售人員張三剛通過qq群聊了一個客戶,咨詢了"Python全棧開發課程",錄入了CRM
- 張三 回訪了一個 一個月多前咨詢的老客戶,老客戶說最近考慮報名,讓張三 下周聯系他辦報名手續, 張三把這個回訪信息 錄入了crm
- 李四 今天錄入了8個新客戶,但發現有一個客戶在錄入時,系統提示,此客戶信息已存在,於是就在客戶庫查了一下,發現 此客戶 已被 張 三 在上周錄入了,銷售部有規定,在客戶被錄入一個月內,其它銷售是不能搶這個單的,於是就提醒張三,讓他跟這個客戶主動再跟進一下
- 李四今天 有一個客戶要報名,李四給客戶發了在線報名 鏈接,要求其填寫一些個人信息,上傳證件照片等,交了500報名費后,將其正式添加到了報名的 班級里
- 銷售主管 BigSB 查看了今天的銷售報表, 查看了每個銷售的最近一周 咨詢的客戶量,成單比, 每個課程 分別 報名了多少學員, 這些客戶 都是從哪些渠道 過來的
二. 講師:
- 講師Alex 今天 要給 Python自動化 周未班上課, 上課前要進行點名, 於是創建了一條生課紀錄 ,這條上課記錄關聯 着每個學員 這節課的 出勤狀態,alex 邊點名邊在系統 中紀錄每個學員的狀態 ,簽到、遲到或缺勤。
- 今天的課上完后,ALEX給大家留了作業,在系統 里 找到今天 的上課記錄,把作業 需求 寫到了 上課紀錄 里
- 過了一周, Alex 登錄 系統 下載了所有學員這節課的作業 , 為每個學員批改了作業 並將學員的成績紀錄在了系統 里
三. 學員:
- 學員小明 報名了“Go語言開發課程第2期周未班”, 交完報名費后,招生老師 給他發了一個報名地址 要求其填寫,填寫了個人信息 並上傳了證件信息, 提交后, 過了一會,就發現自己的qq郵箱里收到了一封 老男孩學校的郵件, 告知他 已為其 生成了 學員賬號,他按照郵件 提示 登錄 了 老男孩的學員系統 ,看到系統 中可以 進入自己的班級,不過現在班級里 還沒有上課紀錄, 他還能在線查看 他的學員合同
- 過了一周, 正式上課了,上了一天課,講師Alex布置了作業 , 小明過了幾天 完成 作業后,登錄 學員管理系統 , 發現有一條 自己的上課記錄, 他點進去,看到了當節課的 作業 需求,及提交作業的方式 ,他只需要把作業 打包成.zip格式 ,直接拖拽到頁面上的交作業區就可以了。
- 過了兩天, 小明收到郵件提醒 ,說自己作業 得了個A,非常 的開森。
- 小明學了幾個月好,發現老男孩講師講的好,自己學的也不錯,於是極力推薦自己的2個朋友也來學習, 於是在自己的學員系統 里錄入了2條推薦朋友學習的信息, 沒過一會, 小明之前的招生老師就聯系他說,已經收到他的推薦名單,很快就會聯系 小明的朋友 。
好啦, 業務場景也分析完了,接下來我們終於可以開始搞事情啦!
表結構設計
在設計表結構前,咱們先創建好一個項目吧,項目名就叫PerfectCRM,app名叫crm

我這里先列出來我們大體需要的表,爾等先過目一下,然后我們再分別為什么需要每個具體的表,及這個表里要存什么樣的數據
from django.db import models
# Create your models here.
class Customer(models.Model):
'''存儲所有客戶信息'''
pass
class Enrollment(models.Model):
'''存儲已報名學員的信息'''
pass
class CustomerFollowUp(models.Model):
'''存儲客戶的后續跟進信息'''
pass
class ClassList(models.Model):
'''存儲班級信息'''
pass
class Course(models.Model):
'''存儲所開設課程的信息'''
pass
class CourseRecord(models.Model):
'''存儲各班級的上課記錄'''
pass
class StudyRecord(models.Model):
'''存儲所有學員的詳細的學習成績情況'''
pass
class UserProfile(models.Model):
'''存儲所有講師\銷售人員\ 學員 用戶信息'''
pass
class Role(models.Model):
'''角色信息'''
pass
class Branch(models.Model):
'''存儲所有校區'''
pass
接下來分別解釋每張表
1. Customer表, 主要給銷售人員用, 存儲所有客戶信息,里面要記錄客戶來源\姓名\qq \客戶來源\咨詢的內容等
class Customer(models.Model): '''存儲所有客戶信息''' #客戶在咨詢時,多是通過qq,所以這里就把qq號做為唯一標記客戶的值,不能重復 qq = models.CharField(max_length=64,unique=True,help_text=u'QQ號必須唯一') qq_name = models.CharField(u'QQ名稱',max_length=64,blank=True,null=True) #客戶只要沒報名,你沒理由要求人家必須告訴你真實姓名及其它更多私人信息呀 name = models.CharField(u'姓名',max_length=32,blank=True,null=True) sex_type = (('male',u'男'),('female',u'女')) sex = models.CharField(u"性別",choices=sex_type,default='male',max_length=32) birthday = models.DateField(u'出生日期',max_length=64,blank=True,null=True,help_text="格式yyyy-mm-dd") phone = models.BigIntegerField(u'手機號',blank=True,null=True) email = models.EmailField(u'常用郵箱',blank=True,null=True) id_num = models.CharField(u'身份證號',blank=True,null=True,max_length=64) source_type = (('qq',u"qq群"), ('referral',u"內部轉介紹"), ('website',u"官方網站"), ('baidu_ads',u"百度廣告"), ('qq_class',u"騰訊課堂"), ('school_propaganda',u"高校宣講"), ('51cto',u"51cto"), ('others',u"其它"), ) #這個客戶來源渠道是為了以后統計各渠道的客戶量\成單量,先分類出來 source = models.CharField(u'客戶來源',max_length=64, choices=source_type,default='qq') #我們的很多新客戶都是老學員轉介紹來了,如果是轉介紹的,就在這里紀錄是誰介紹的他,前提這個介紹人必須是我們的老學員噢,要不然系統里找不到 referral_from = models.ForeignKey('self',verbose_name=u"轉介紹自學員",help_text=u"若此客戶是轉介紹自內部學員,請在此處選擇內部\學員姓名",blank=True,null=True,related_name="internal_referral") #已開設的課程單獨搞了張表,客戶想咨詢哪個課程,直接在這里關聯就可以 course = models.ForeignKey("Course",verbose_name=u"咨詢課程") class_type_choices = (('online', u'網絡班'), ('offline_weekend', u'面授班(周末)',), ('offline_fulltime', u'面授班(脫產)',), ) class_type = models.CharField(u"班級類型",max_length=64,choices=class_type_choices) customer_note = models.TextField(u"客戶咨詢內容詳情",help_text=u"客戶咨詢的大概情況,客戶個人信息備注等...") work_status_choices = (('employed','在職'),('unemployed','無業')) work_status = models.CharField(u"職業狀態",choices=work_status_choices,max_length=32,default='employed') company = models.CharField(u"目前就職公司",max_length=64,blank=True,null=True) salary = models.CharField(u"當前薪資",max_length=64,blank=True,null=True) status_choices = (('signed',u"已報名"),('unregistered',u"未報名")) status = models.CharField(u"狀態",choices=status_choices,max_length=64,default=u"unregistered",help_text=u"選擇客戶此時的狀態") #課程顧問很得要噢,每個招生老師錄入自己的客戶 consultant = models.ForeignKey("UserProfile",verbose_name=u"課程顧問") date = models.DateField(u"咨詢日期",auto_now_add=True) def __str__(self): return u"QQ:%s -- Name:%s" %(self.qq,self.name) class Meta: #這個是用來在admin頁面上展示的,因為默認顯示的是表名,加上這個就變成中文啦 verbose_name = u'客戶信息表' verbose_name_plural = u"客戶信息表"
2. 學員報名表,這里為什么要把客戶信息表 和 這個學員報名表分開呢? 因內一個學員可以報多個課程 ,每個課程 都需要單獨記錄學習成績呀什么的,所以每報一個課程 ,就在這里生成 一條相應的報名記錄
class Enrollment(models.Model): '''存儲學員報名的信息''' #所有報名的學生 肯定是來源於客戶信息表的,先咨詢,后報名嘛 customer = models.ForeignKey(Customer) school = models.ForeignKey('Branch', verbose_name='校區') #選擇他報的班級,班級是關聯課程的,比如python開發10期 course_grade = models.ForeignKey("ClassList", verbose_name="所報班級") why_us = models.TextField("為什么報名老男孩", max_length=1024, default=None, blank=True, null=True) your_expectation = models.TextField("學完想達到的具體期望", max_length=1024, blank=True, null=True) contract_agreed = models.BooleanField("我已認真閱讀完培訓協議並同意全部協議內容") contract_approved = models.BooleanField("審批通過", help_text=u"在審閱完學員的資料無誤后勾選此項,合同即生效") enrolled_date = models.DateTimeField(auto_now_add=True, auto_created=True, verbose_name="報名日期") memo = models.TextField('備注', blank=True, null=True) def __str__(self): return "<%s 課程:%s>" %(self.customer ,self.course_grade) class Meta: verbose_name = '學員報名表' verbose_name_plural = "學員報名表" unique_together = ("customer", "course_grade") #這里為什么要做個unique_together聯合唯一?因為老男孩有很多個課程, 學生學完了一個覺得好的話,以后還可以再報其它班級, #每報一個班級,就得單獨創建一條報名記錄,所以這里想避免重復數據的話,就得搞個"客戶 + 班級"的聯合唯一嘍
3. 客戶跟進表,這張表的意義很容易理解, 一個客戶今天咨詢后,你錄入到了客戶信息表,但他沒報名, 所以過了一段時間,銷售還得再跟他聊聊吧,聊完后,結果又沒報,那也得紀錄下來吧,因為每個銷售每天要聊很多人,你不紀錄的話, 可能下次再跟這個人聊時,你早已忘記上次聊了什么了, 這樣會讓客戶覺得這個銷售不專業,相反,如果把每次跟進的內容都紀錄下來, 過了幾個月,這個客戶再跟你聊時,竟然發現,你還記得他的所有情況,他就覺得你很重視他,說不定一感動就報名了,哈哈。 所以,一條客戶信息可能會對應多條跟進記錄,是個1對多的關系,必須單獨搞張表來記錄
class CustomerFollowUp(models.Model): '''存儲客戶的后續跟進信息''' customer = models.ForeignKey(Customer,verbose_name=u"所咨詢客戶") note = models.TextField(u"跟進內容...") status_choices = ((1,u"近期無報名計划"), (2,u"2個月內報名"), (3,u"1個月內報名"), (4,u"2周內報名"), (5,u"1周內報名"), (6,u"2天內報名"), (7,u"已報名"), (8,u"已交全款"), ) status = models.IntegerField(u"狀態",choices=status_choices,help_text=u"選擇客戶此時的狀態") consultant = models.ForeignKey("UserProfile",verbose_name=u"跟蹤人") date = models.DateField(u"跟進日期",auto_now_add=True) def __str__(self): return u"%s, %s" %(self.customer,self.status) class Meta: verbose_name = u'客戶咨詢跟進記錄' verbose_name_plural = u"客戶咨詢跟進記錄"
4. 班級表, 學生以班級為單位管理,這個表被學員表反向關聯, 即每個學員報名時需要選擇班級
class ClassList(models.Model): '''存儲班級信息''' #創建班級時需要選擇這個班所學的課程 branch = models.ForeignKey("Branch",verbose_name="校區") course = models.ForeignKey("Course",verbose_name=u"課程") class_type_choices = ((0,'面授'),(1,'隨到隨學網絡')) class_type = models.SmallIntegerField(choices=class_type_choices,default=0) total_class_nums = models.PositiveIntegerField("課程總節次",default=10) semester = models.IntegerField(u"學期") price = models.IntegerField(u"學費", default=10000) start_date = models.DateField(u"開班日期") graduate_date = models.DateField(u"結業日期", blank=True, null=True) #選擇這個班包括的講師,可以是多個 teachers = models.ManyToManyField("UserProfile", verbose_name=u"講師") def __str__(self): return "%s(%s)" % (self.course, self.semester) class Meta: verbose_name = u'班級列表' verbose_name_plural = u"班級列表" #為避免重復創建班級,課程名+學期做聯合唯一 unique_together = ("course", "semester") #自定義方法,反向查找每個班級學員的數量,在后台admin里 list_display加上這個"get_student_num"就可以看到 def get_student_num(self): return "%s" % self.customer_set.select_related().count() get_student_num.short_description = u'學員數量'
5. 課程表,存儲課程介紹\大綱等基本信息
class Course(models.Model): '''存儲所開設課程的信息''' name = models.CharField(u"課程名",max_length=64,unique=True) description = models.TextField("課程描述") outline = models.TextField("課程大綱") period = models.IntegerField("課程周期(Month)") def __str__(self): return self.name
6. 上課紀錄表,每個班級都要上很多次課,講師每上一次課的紀錄都要紀錄下來,以后可以方便統計講師工資什么的
class CourseRecord(models.Model): '''存儲各班級的上課記錄''' #講師創建上課紀錄時要選擇是上哪個班的課 course = models.ForeignKey(ClassList, verbose_name="班級(課程)") day_num = models.IntegerField("節次", help_text="此處填寫第幾節課或第幾天課程...,必須為數字") date = models.DateField(auto_now_add=True, verbose_name="上課日期") teacher = models.ForeignKey("UserProfile", verbose_name="講師") has_homework = models.BooleanField(default=True, verbose_name="本節有作業") homework_title = models.CharField(max_length=128,blank=True,null=True) homework_requirement = models.TextField(blank=True,null=True) def __str__(self): return "%s 第%s天" % (self.course, self.day_num) class Meta: verbose_name = u'上課紀錄' verbose_name_plural = u"上課紀錄" unique_together = ('course', 'day_num')
7. 學員學習紀錄表,思考一下,如果你想實現紀錄每位學員的詳細學習紀錄,即精確到每節課的成績\出勤情況,怎么辦?其實很簡單, 先來看一下此時班級\上課紀錄\學員學習紀錄的關系圖:

class StudyRecord(models.Model): '''存儲所有學員的詳細的學習成績情況''' student = models.ForeignKey("Customer",verbose_name=u"學員") course_record = models.ForeignKey(CourseRecord, verbose_name=u"第幾天課程") record_choices = (('checked', u"已簽到"), ('late',u"遲到"), ('noshow',u"缺勤"), ('leave_early',u"早退"), ) record = models.CharField(u"上課紀錄",choices=record_choices,default="checked",max_length=64) score_choices = ((100, 'A+'), (90,'A'), (85,'B+'), (80,'B'), (70,'B-'), (60,'C+'), (50,'C'), (40,'C-'), (-50,'D'), (0,'N/A'), (-100,'COPY'), (-1000,'FAIL'), ) score = models.IntegerField(u"本節成績",choices=score_choices,default=-1) date = models.DateTimeField(auto_now_add=True) note = models.CharField(u"備注",max_length=255,blank=True,null=True) def __str__(self): return u"%s,學員:%s,紀錄:%s, 成績:%s" %(self.course_record,self.student.name,self.record,self.get_score_display()) class Meta: verbose_name = u'學員學習紀錄' verbose_name_plural = u"學員學習紀錄" #一個學員,在同一節課只可能出現一次,所以這里把course_record + student 做成聯合唯一 unique_together = ('course_record','student')
可以看出,一個班級對應多節課,每節課又對應多個學生的出勤和成績,我們已經通過班級表(”ClassList”)和上課紀錄表(”CourseRecord”)存儲了班級信息和每節上課紀錄,想存學生的每節課學習紀錄的話只需要再搞一個表就可以了。
8. 用戶表,存儲銷售、講師賬戶信息
這里我們用django自帶的認證系統,並對其進行自定制
class UserProfile(auth.AbstractBaseUser, auth.PermissionsMixin): email = models.EmailField( verbose_name='email address', max_length=255, unique=True, ) password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a class='btn-link' href='password'>重置密碼</a>''')) is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField( verbose_name='staff status', default=True, help_text='Designates whether the user can log into this admin site.', ) name = models.CharField(max_length=32) #role = models.ForeignKey("Role",verbose_name="權限角色") branch = models.ForeignKey("Branch",verbose_name="所屬校區",blank=True,null=True) roles = models.ManyToManyField('Role',blank=True) memo = models.TextField('備注', blank=True, null=True, default=None) date_joined = models.DateTimeField(blank=True, null=True, auto_now_add=True) USERNAME_FIELD = 'email' # REQUIRED_FIELDS = ['name','token','department','tel','mobile','memo'] REQUIRED_FIELDS = ['name'] def get_full_name(self): # The user is identified by their email address return self.email def get_short_name(self): # The user is identified by their email address return self.email def __str__(self): # __str__ on Python 2 return self.email # def has_perm(self, perm, obj=None): # "Does the user have a specific permission?" # # Simplest possible answer: Yes, always # return True def has_perms(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True @property def is_superuser(self): "Is the user a member of staff?" # Simplest possible answer: All admins are staff return self.is_admin class Meta: verbose_name = '用戶信息' verbose_name_plural = u"用戶信息" objects = auth.UserManager() class Meta: verbose_name = 'CRM賬戶' verbose_name_plural = 'CRM賬戶'
9. 角色表,用於角色划分,用於權限管理,權限功能我們后面會實現,這里只在表里先存個簡單的角色名
class Role(models.Model): '''角色信息''' name = models.CharField(max_length=32,unique=True) menus = models.ManyToManyField('FirstLayerMenu',blank=True) def __str__(self): return self.name
10. 校區表,存儲不同校區
class Branch(models.Model): '''存儲所有校區''' name = models.CharField(max_length=64,unique=True) def __str__(self): return self.name
11. 菜單表,不同的角色看到的菜單不同, 我們支持動態菜單 ,所以需要把菜單 以及 和角色的關聯存下來
class FirstLayerMenu(models.Model): '''第一層側邊欄菜單''' name = models.CharField('菜單名',max_length=64) url_type_choices = ((0,'related_name'),(1,'absolute_url')) url_type = models.SmallIntegerField(choices=url_type_choices,default=0) url_name = models.CharField(max_length=64,unique=True) order = models.SmallIntegerField(default=0,verbose_name='菜單排序') sub_menus = models.ManyToManyField('SubMenu',blank=True) def __str__(self): return self.name
12. 二級菜單表, 還可以支持2級子菜單
class SubMenu(models.Model): '''第二層側邊欄菜單''' name = models.CharField('二層菜單名', max_length=64) url_type_choices = ((0,'related_name'),(1,'absolute_url')) url_type = models.SmallIntegerField(choices=url_type_choices,default=0) url_name = models.CharField(max_length=64, unique=True) order = models.SmallIntegerField(default=0, verbose_name='菜單排序') def __str__(self): return self.name
13. 繳費記錄
class PaymentRecord(models.Model): enrollment = models.ForeignKey("Enrollment") pay_type_choices = (('deposit', u"訂金/報名費"), ('tution', u"學費"), ('refund', u"退款"), ) pay_type = models.CharField("費用類型", choices=pay_type_choices, max_length=64, default="deposit") paid_fee = models.IntegerField("費用數額", default=0) note = models.TextField("備注",blank=True, null=True) date = models.DateTimeField("交款日期", auto_now_add=True) consultant = models.ForeignKey(UserProfile, verbose_name="負責老師", help_text="誰簽的單就選誰") def __str__(self): return "%s, 類型:%s,數額:%s" %(self.enrollment.customer, self.pay_type, self.paid_fee) class Meta: verbose_name = '交款紀錄' verbose_name_plural = "交款紀錄"
好啦,表基本都建完了,接下來同步數據庫,不過在同步數據庫前,要改一下settings.py, 因為我們自定義了django的認證表,所以需要明確的告訴django,用我們改過的過來做默認的認證系統。
在settings.py中添加以下行,格式為 app.modelname
AUTH_USER_MODEL = 'crm.UserProfile'
最后一步,同步數據庫!
python3 manage.py makemigrations python3 manage.py migrate
伸個懶腰,出去擼一發,敬請期待下篇....
