Django之路 - 項目實戰之<教育行業CRM開發>


本節內容

 

業務痛點分析

項目需求討論

使用場景分析

表結構設計

 

業務痛點分析

我2013年剛加入老男孩教育的時候,學校就一間教室,2個招生老師,招了學生后,招生老師就在自己的excel表里記錄一下,每月算工資時,就按這個表來統計招生提成, 后來學校大了點,教室變成了3間,招生老師變成了4個人,招的學生也開始多了起來,不過大家依然是招了學生就紀錄在自己的excel里,但問題開始出現了,我們的招生多是通過網絡qq聊天在線咨詢,好多客戶需要聊很久才能轉化成學員,經常會出現一個客戶跟一個招生老師聊過后,過了一段時間卻在另一個招生老師那報名了。 於是爭執就出現了,A銷售說這個人是先找我咨詢的,我幫他回答了大多數問題,報名提成卻算成B的,不公平。B銷售也會講,這個客戶找他咨詢時並未說自己之前跟其它銷售聊過呀,所以對B來講,這就是個新客戶呀,並且是在B這報的名, 憑什么要分提成給A呀。為了解決這個問題,於是想出一個辦法,搞了一個機器做共享服務器,共享服務器上搞了個統一的客戶信息excel表,大家每人聊過的客戶都在這個表里紀錄, 這樣每個人錄入前,先在表格里全局查一下,這個客戶的qq號是不是已經在表里了,這樣就能避免沖突了。 但用過共享文件的應該都遇到過一個問題就是,為保證數據一致性,同一時間系統只允許一個用戶修改數據, 但我們的每個招生老師一上班,就會打開這個共享文件,隨時聊的學生,隨時會錄入到表里。但這個限制使的大家,只要一有人錄入信息,就得要求其它銷售人員都把文件先關閉,錄入信息后其它人才能再用,這搞的大家很難受。  所以銷售人員經常讓我幫開發個系統,可以解決一些類似這樣的問題。

 

另外, 我們在講課時, 為了保證和檢驗學員的學習效果, 每節課講完時都會給學生部置一個作業,要求他必須在下節上課前完成並提交作業,老師會給學員統一批作業,作業成績也紀錄在excel表中,就像下圖一樣。每個老師維護自己班級的作業,校長如果想看各個班級的成績,還要跟每個老師要學員成績表,很不方便, 當時校長就跟我講,學員的成績\出勤情況等要是也能統一管理就好了。

 

 

 

於是我心里也一直紀着這個事,想幫學校開發一個學員開發一個類似CRM(客戶關系管理軟件)的系統,集銷售管理\學員管理等功能於一體。但平常要上班,周未還要講課,一直沒時間,終於有一次,我要去美帝度假,飛機要飛13個小時才到紐約,在飛機上突然想,反正也是沒事干, 不如就開發這個東西吧, 於是一路未眠,狂寫了近千行代碼,飛機的上的美女空乘都心疼的多給我倒了2杯咖啡,哈哈,下飛機時,已是兩眼痛紅,不過,這個學員管理系統的雛形也做出來了,接下來幾天在紐約又完善了下細節,於是就開始上線讓大家用了。到現在,這個系統在公司已經用了一年多了,大家每天都在使用,之前的痛點都解決了,特別是銷售人員, 工作已經離不開這個系統了,自己做的東西幫別人解決具體問題,心里還是蠻開森的!

 

 

個人覺得這個學員管理系統的挺適合新手練習的,難度適中,用戶的知識點也比較綜合,所以把學校里的系統簡化了一下,提練成了一個教學項目,下面我們就一起來做一個嘍。

 

噢,對了,最后說一下這個項目涉及到的知識點,請確保你以充分掌握了下面所列知識點再學習此項目噢!

  1. Django

  2. JQuery

  3. BootStrap

  4. Ajax

  5. HTMS\CSS

 

 

項目需求討論

首先給我們的項目起個名字吧,這個系統要同時支持銷售管理\學員管理\講師管理等功能,功能比較雜,不能稱之為嚴格意上的CRM,因為CRM一般只包括銷售管理,but anyway, who cares,我們就叫它”老男孩crm管理系統”吧,

 

起好了名字,開始動手寫之前, 肯定要把需求想清楚,需求想不清楚就開始寫的話,等於給自己挖坑,你肯定不想出現寫了5千行代碼后,突然發現,需求搞錯了,還要重新推到重來的事情吧。所以,現在靜下心,把需求想明白,畫好思維導圖,跟同事多討論應用場景,做了各方面論證后,再開始動工噢。

 

我們的系統的用戶分3種,銷售\學生\講師,這3個角色關注的事情是不同的, 銷售只關注招了多少學員,講師關注自己管理的班級學習成績怎樣,學員只關注自己的學習成績。 因此在想需求時,你要從每個角色出發,看他關心的是什么, 於是我畫出了這個思維導圖

 


根據思維導圖,我們總結出以下具體需求:

  1. 把用戶分為銷售\學員\講師3種角色,每個角色關心的事情不同,所以有要不同的用戶視圖,即銷售人員登陸后只需要看他與他工作相關的就可以,講師關心的事情不需要在銷售視圖里顯示
  2. 銷售人員可以錄入客戶信息,和后續跟進信息,因為一個客戶可能要跟進好幾次才會報名。 可以多種條件過濾查詢用戶,可以查看自己的銷售業績報表
  3. 學員主要2個功能,查詢成績\提交作業
  4. 講師的主要功能是管理班級\ 批作業\上課點名
  5. 雖然現在只有一個校區,但要考慮到以后的擴展,以后全國可能有好多個校區,不同校區之間的數據應該是隔離的
  6. 這個系統里存放着大量的客戶信息\學員數據等,都是公司的機密信息,設計系統時就要考慮到權限問題,不同的角色要有不同的權限,同一角色的不同用戶也要允許有不同的權限

 

使用場景分析

為了更加理清我們的項目開發需求,在動手寫代碼前,建議再有一個業務場景分析的步驟,即從用戶角度寫出你使用這個項目的具體場景,我們這里分為銷售、講師、學員3個角色,我分別給每個角色列出了幾個使用場景:

 

一. 銷售:

  1. 銷售人員張三剛通過qq群聊了一個客戶,咨詢了"Python全棧開發課程",錄入了CRM
  2. 張三 回訪了一個 一個月多前咨詢的老客戶,老客戶說最近考慮報名,讓張三 下周聯系他辦報名手續, 張三把這個回訪信息 錄入了crm
  3. 李四 今天錄入了8個新客戶,但發現有一個客戶在錄入時,系統提示,此客戶信息已存在,於是就在客戶庫查了一下,發現 此客戶 已被  張 三  在上周錄入了,銷售部有規定,在客戶被錄入一個月內,其它銷售是不能搶這個單的,於是就提醒張三,讓他跟這個客戶主動再跟進一下
  4. 李四今天 有一個客戶要報名,李四給客戶發了在線報名 鏈接,要求其填寫一些個人信息,上傳證件照片等,交了500報名費后,將其正式添加到了報名的 班級里
  5. 銷售主管 BigSB  查看了今天的銷售報表, 查看了每個銷售的最近一周 咨詢的客戶量,成單比, 每個課程 分別 報名了多少學員, 這些客戶 都是從哪些渠道 過來的

二. 講師:

  1. 講師Alex 今天 要給 Python自動化 周未班上課, 上課前要進行點名, 於是創建了一條生課紀錄 ,這條上課記錄關聯 着每個學員 這節課的 出勤狀態,alex 邊點名邊在系統 中紀錄每個學員的狀態 ,簽到、遲到或缺勤。
  2. 今天的課上完后,ALEX給大家留了作業,在系統 里 找到今天 的上課記錄,把作業 需求 寫到了 上課紀錄 里
  3. 過了一周, Alex 登錄 系統 下載了所有學員這節課的作業 , 為每個學員批改了作業 並將學員的成績紀錄在了系統 里

 

三. 學員:

  1. 學員小明 報名了“Go語言開發課程第2期周未班”, 交完報名費后,招生老師 給他發了一個報名地址 要求其填寫,填寫了個人信息 並上傳了證件信息, 提交后, 過了一會,就發現自己的qq郵箱里收到了一封 老男孩學校的郵件, 告知他 已為其 生成了 學員賬號,他按照郵件 提示 登錄 了 老男孩的學員系統 ,看到系統 中可以  進入自己的班級,不過現在班級里 還沒有上課紀錄, 他還能在線查看 他的學員合同
  2. 過了一周, 正式上課了,上了一天課,講師Alex布置了作業 , 小明過了幾天 完成 作業后,登錄 學員管理系統 , 發現有一條 自己的上課記錄, 他點進去,看到了當節課的 作業 需求,及提交作業的方式 ,他只需要把作業 打包成.zip格式 ,直接拖拽到頁面上的交作業區就可以了。
  3. 過了兩天, 小明收到郵件提醒 ,說自己作業 得了個A,非常 的開森。
  4. 小明學了幾個月好,發現老男孩講師講的好,自己學的也不錯,於是極力推薦自己的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"客戶信息表"
Customer

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聯合唯一?因為老男孩有很多個課程, 學生學完了一個覺得好的話,以后還可以再報其它班級,
        #每報一個班級,就得單獨創建一條報名記錄,所以這里想避免重復數據的話,就得搞個"客戶 + 班級"的聯合唯一嘍
Enrollment

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"客戶咨詢跟進記錄"
CustomerFollowUp

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'學員數量'
ClassList

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
Course

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')
CourseRecord

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')
StudyRecord

可以看出,一個班級對應多節課,每節課又對應多個學生的出勤和成績,我們已經通過班級表(”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賬戶'
UserProfile

 

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
Role

 

10. 校區表,存儲不同校區

class Branch(models.Model):
    '''存儲所有校區'''
    name = models.CharField(max_length=64,unique=True)
    def __str__(self):
        return self.name
Branch

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
FirstLayerMenu

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
SubMenu

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 = "交款紀錄"
PaymentRecord

 

好啦,表基本都建完了,接下來同步數據庫,不過在同步數據庫前,要改一下settings.py, 因為我們自定義了django的認證表,所以需要明確的告訴django,用我們改過的過來做默認的認證系統。

在settings.py中添加以下行,格式為 app.modelname 

AUTH_USER_MODEL = 'crm.UserProfile'

  

 

 

最后一步,同步數據庫! 

python3 manage.py makemigrations 
python3 manage.py migrate 

  

 

伸個懶腰,出去擼一發,敬請期待下篇.... 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM