項目一:CRM(客戶關系管理系統)--1


Djangoadmin已經為我們做好了,很完善的后台管理體系,但頁面過於丑陋,自定義的能力還是有局限性的。特此,重寫admin后台管理體系,同時也是考慮到其他輕量級框架並沒有類似Django這么完善的admin!寫成獨立的app,便宜更好的進行復用遷移。

1. 創建工程和項目

命名根據自己的喜好吧,推薦使用PyCharm進行創建,減少一些配置操作,當然不要忘記在settings.py的一些配置!

目錄結構如下:

├─consultant   #銷售
│  ├─migrations
│  │  └─__pycache__
│  └─__pycache__
├─CRM     #主app
│  ├─migrations
│  │  └─__pycache__
│  └─__pycache__
├─king_admin  #重構的admin
│  ├─migrations
│  │  └─__pycache__
│  ├─templatetags
│  │  └─__pycache__
│  └─__pycache__
├─PrefectCRM_new  #工程
│  └─__pycache__
├─statics
│  ├─css
│  ├─imgs
│  ├─js
│  └─plugins
├─student   #學生
│  ├─migrations
│  │  └─__pycache__
│  └─__pycache__
├─templates
│  ├─consultant
│  ├─king_admin
│  └─student
└─utils
由於在數據庫表中,綁定了一些路由映射關系,順便將路由的結構也顯示一下:
 1 #這是總的urls.py中的配置,獨立將在下面一次貼出來
 2 from django.conf.urls import url,include
 3 from django.contrib import admin
 4 urlpatterns = [
 5     url(r'^admin/', admin.site.urls),
 6     url(r'^crm/', include('CRM.urls')),
 7     url(r'^student/', include('student.urls')),
 8     url(r'^consultant/', include('consultant.urls')),
 9     url(r'^king_admin/', include('king_admin.urls')),
10 ]

 

2. 表結構設計

表結構設計是非常關鍵的步驟,也是最難點!這會影響你以后的程序設計,稍有疏漏,很可能會導致你要進行代碼重構或者一路填坑...

由於要做的是CRM系統,這里就以XXX公司作為案例。

在進行具體的代碼之前,我們先進行一些數據關系的處理,這里推薦大家使用ER圖(mac上我使用MindNode)。我這里是通過先前搞好的數據結構和ER圖,就不在重復贅述,直接上處理好后的圖和代碼: 

ER思維導圖:

數據關系圖:

 在主appCRM中的models.py中創建數據結構:

  1 from django.db import models
  2 from django.contrib.auth.models import User
  3 # Create your models here.
  4 class Customer(models.Model):
  5     '''客戶信息表'''
  6     name = models.CharField(max_length=32,blank=True,null=True)
  7     qq = models.CharField(max_length=64,unique=True)
  8     qq_name = models.CharField(max_length=64,blank=True,null=True)
  9     phone = models.CharField(max_length=64,blank=True,null=True)
 10     source_choices = ((0,'轉介紹'),
 11                       (1,'QQ群'),
 12                       (2,'官網'),
 13                       (3,'百度推廣'),
 14                       (4,'51CTO'),
 15                       (5,'知乎'),
 16                       (6,'市場推廣')
 17                       )
 18     source = models.SmallIntegerField(choices=source_choices)
 19     referral_from = models.CharField(verbose_name="轉介紹人qq",max_length=64,blank=True,null=True)
 20     consult_course = models.ForeignKey("Course",verbose_name="咨詢課程")
 21     content = models.TextField(verbose_name="咨詢詳情")
 22     tags = models.ManyToManyField("Tag",blank=True)
 23     status_choices = ((0,'已報名'),
 24                       (1,'未報名'),
 25                       )
 26     status = models.SmallIntegerField(choices=status_choices,default=1)
 27     consultant = models.ForeignKey("UserProfile")
 28     memo = models.TextField(blank=True,null=True)
 29     date = models.DateTimeField(auto_now_add=True)
 30     def __str__(self):
 31         return self.qq
 32     class Meta:
 33         verbose_name ="客戶表"
 34         verbose_name_plural ="客戶表"
 35 class Tag(models.Model):
 36     name = models.CharField(unique=True,max_length=32)
 37     def __str__(self):
 38         return self.name
 39     class Meta:
 40         verbose_name = "標簽"
 41         verbose_name_plural = "標簽"
 42 class CustomerFollowUp(models.Model):
 43     '''客戶跟進表'''
 44     customer = models.ForeignKey("Customer")
 45     content = models.TextField(verbose_name="跟進內容")
 46     consultant = models.ForeignKey("UserProfile")
 47     intention_choices  = ((0,'2周內報名'),
 48                           (1,'1個月內報名'),
 49                           (2,'近期無報名計划'),
 50                           (3,'已在其它機構報名'),
 51                           (4,'已報名'),
 52                           (5,'已拉黑'),
 53                           )
 54     intention = models.SmallIntegerField(choices=intention_choices)
 55     date = models.DateTimeField(auto_now_add=True)
 56     def __str__(self):
 57         return "<%s : %s>" %(self.customer.qq,self.intention)
 58     class Meta:
 59         verbose_name = '客戶追蹤'
 60         verbose_name_plural = "客戶追蹤"
 61 class Course(models.Model):
 62     '''課程表'''
 63     name = models.CharField(max_length=64,unique=True)
 64     price = models.PositiveSmallIntegerField()
 65     period = models.PositiveSmallIntegerField(verbose_name="周期(月)")
 66     outline = models.TextField()
 67     def __str__(self):
 68         return self.name
 69     class Meta:
 70         verbose_name = "課程表"
 71         verbose_name_plural = "課程表"
 72 class Branch(models.Model):
 73     '''校區'''
 74     name = models.CharField(max_length=128,unique=True)
 75     addr = models.CharField(max_length=128)
 76     def __str__(self):
 77         return self.name
 78     class Meta:
 79         verbose_name = "校區"
 80         verbose_name_plural = "校區"
 81 class ClassList(models.Model):
 82     '''班級表'''
 83     branch = models.ForeignKey("Branch",verbose_name="校區")
 84     course = models.ForeignKey("Course")
 85     class_type_choices = ((0,'面授(脫產)'),
 86                           (1,'面授(周末)'),
 87                           (2,'網絡班')
 88                           )
 89     class_type = models.SmallIntegerField(choices=class_type_choices,verbose_name="班級類型")
 90     semester = models.PositiveSmallIntegerField(verbose_name="學期")
 91     teachers = models.ManyToManyField("UserProfile")
 92     start_date = models.DateField(verbose_name="開班日期")
 93     end_date = models.DateField(verbose_name="結業日期",blank=True,null=True)
 94     def __str__(self):
 95         return "%s %s %s" %(self.branch,self.course,self.semester)
 96     class Meta:
 97         unique_together = ('branch','course','semester')
 98         verbose_name_plural = "班級"
 99         verbose_name = "班級"
100 class CourseRecord(models.Model):
101     '''上課記錄'''
102     from_class = models.ForeignKey("ClassList",verbose_name="班級")
103     day_num = models.PositiveSmallIntegerField(verbose_name="第幾節(天)")
104     teacher = models.ForeignKey("UserProfile")
105     has_homework = models.BooleanField(default=True)
106     homework_title = models.CharField(max_length=128,blank=True,null=True)
107     homework_content = models.TextField(blank=True,null=True)
108     outline = models.TextField(verbose_name="本節課程大綱")
109     date = models.DateField(auto_now_add=True)
110     def __str__(self):
111         return "%s %s" %(self.from_class,self.day_num)
112     class Meta:
113         unique_together = ("from_class", "day_num")
114         verbose_name_plural = "上課記錄"
115 class StudyRecord(models.Model):
116     '''學習記錄'''
117     student = models.ForeignKey("Enrollment")
118     course_record = models.ForeignKey("CourseRecord")
119     attendance_choices = ((0,'已簽到'),
120                           (1,'遲到'),
121                           (2,'缺勤'),
122                           (3,'早退'),
123                           )
124     attendance = models.SmallIntegerField(choices=attendance_choices,default=0)
125     score_choices = ((100,"A+"),
126                      (90,"A"),
127                      (85,"B+"),
128                      (80,"B"),
129                      (75,"B-"),
130                      (70,"C+"),
131                      (60,"C"),
132                      (40,"C-"),
133                      (-50,"D"),
134                      (-100,"COPY"),
135                      (0,"N/A"),
136                      )
137     score = models.SmallIntegerField(choices=score_choices,default=0)
138     memo = models.TextField(blank=True,null=True)
139     date = models.DateField(auto_now_add=True)
140     def __str__(self):
141         return "%s %s %s" %(self.student,self.course_record,self.score)
142     class Meta:
143         unique_together = ('student','course_record')
144         verbose_name_plural = "學習記錄"
145 class Enrollment(models.Model):
146     '''報名表'''
147     customer = models.ForeignKey("Customer")
148     enrolled_class = models.ForeignKey("ClassList",verbose_name="所報班級")
149     consultant = models.ForeignKey("UserProfile",verbose_name="課程顧問")
150     contract_agreed = models.BooleanField(default=False,verbose_name="學員已同意合同條款")
151     contract_approved = models.BooleanField(default=False,verbose_name="合同已審核")
152     date = models.DateTimeField(auto_now_add=True)
153     def __str__(self):
154         return "%s %s" %(self.customer,self.enrolled_class)
155     class Meta:
156         unique_together = ("customer","enrolled_class")
157         verbose_name_plural = "報名表"
158 class Payment(models.Model):
159     '''繳費記錄'''
160     customer = models.ForeignKey("Customer")
161     course = models.ForeignKey("Course",verbose_name="所報課程")
162     amount = models.PositiveIntegerField(verbose_name="數額",default=500)
163     consultant = models.ForeignKey("UserProfile")
164     date = models.DateTimeField(auto_now_add=True)
165     def __str__(self):
166         return "%s %s" %(self.customer,self.amount)
167     class Meta:
168         verbose_name_plural = "繳費記錄"
169 class UserProfile(models.Model):
170     '''賬號表'''
171     user = models.OneToOneField(User)
172     name = models.CharField(max_length=32)
173     roles = models.ManyToManyField("Role",blank=True)
174     def __str__(self):
175         return self.name
176     class Meta:
177         verbose_name_plural = '用戶賬號'
178 class Role(models.Model):
179     '''角色表'''
180     name = models.CharField(max_length=32,unique=True)
181     menus = models.ManyToManyField("Menu",blank=True)
182     def __str__(self):
183         return self.name
184     class Meta:
185         verbose_name_plural = "角色"
186 class Menu(models.Model):
187     '''菜單'''
188     name = models.CharField(max_length=32)
189     url_name = models.CharField(max_length=64)
190     def __str__(self):
191         return self.name
192     class Meta:
193         verbose_name_plural = '菜單欄'

1.以上內容只是作為參考,並不一定能夠作為生產上的應用,若要上生產還要考慮更多的因素,這里是為寫CRM提供一種通用的思路。
2.如果你考慮到以后的數據會很大,那建議你對數據進行拆分,每個獨立的app中進行獨自的表結構設計,然后在主app中進行處理

 

3. 原生Django的admin分析

在進行分析之前,我們需要創建超級用戶,然后登陸到后台中,添加一些測試數據。

3.1 admin初始化操作

 

 

3.1.1. 創建超級用戶

1 >>> python  manage.py  createsuperuser
2 #下面的用戶名和密碼自己耍吧!

 

3.1.2. 注冊admin

其實,創建完用戶我們就已經可以進入到后台了,將寫好數據表models.py里面的類注冊CRM項目的admin.py中,並進行一些簡單的自定義操作:

 1 from django.contrib import admin
 2 from CRM import models
 3 # Register your models here.
 4 #注冊操作
 5 admin.site.register(models.Branch)
 6 admin.site.register(models.ClassList)
 7 admin.site.register(models.Course)
 8 admin.site.register(models.CourseRecord)
 9 admin.site.register(models.Customer)
10 admin.site.register(models.CustomerFollowUp)
11 admin.site.register(models.Enrollment)
12 admin.site.register(models.Payment)
13 admin.site.register(models.Role)
14 admin.site.register(models.StudyRecord)
15 admin.site.register(models.UserProfile)
16 admin.site.register(models.Tag)
17 admin.site.register(models.Menu)

 

3.1.3. 登陸admin后台

以下是將數據庫表結構設計好后的顯示效果,其中添加了一些測試數據:

 

3.2 自定義顯示樣式

 

我們在上面看到客戶表中顯示的內容太過稀少,而且功能也是少的可憐,好在Django為我們提供了自定義功能。

同樣在admin.py中進行自定義操作:

支持中文:

1 'django.contrib.sessions.middleware.SessionMiddleware',
2 'django.middleware.locale.LocaleMiddleware',    # 設置admin為中文,必須放在django.contrib.sessions....之后

 

修改時區:

1 LANGUAGE_CODE = 'en-us'
2 
3 TIME_ZONE = 'Asia/Shanghai'    # 設置為東八區的時區
4 
5 USE_I18N = True
6 
7 USE_L10N = True
8 
9 USE_TZ = True

 

 1 from django.contrib import admin
 2 from CRM import models
 3 # Register your models here.
 4 #自定義操作
 5 class CustomerAdmin(admin.ModelAdmin):
 6     list_display = ('name', 'id','qq','source','consultant','content','status','date')
 7     list_filter = ('source','consultant','date')
 8     search_fields = ('qq','name')
 9     raw_id_fields = ('consult_course',)
10     filter_horizontal = ('tags',)
11     list_editable = ('status',)
12 class UserProfileAdmin(admin.ModelAdmin):
13     list_display = ('user','name')
14 #注冊操作
15 #注冊操作
16 admin.site.register(models.Branch)
17 admin.site.register(models.ClassList)
18 admin.site.register(models.Course)
19 admin.site.register(models.CourseRecord)
20 admin.site.register(models.Customer, CustomerAdmin)  #這里要添加自定義操作
21 admin.site.register(models.CustomerFollowUp)
22 admin.site.register(models.Enrollment)
23 admin.site.register(models.Payment)
24 admin.site.register(models.Role)
25 admin.site.register(models.StudyRecord)
26 admin.site.register(models.UserProfile, UserProfileAdmin)  #這里要添加自定義操作
27 admin.site.register(models.Tag)
28 admin.site.register(models.Menu)

 

 

 

在這里我們能看到很多功能,搜索,過濾,自定義操作action,排序,分頁(數據量多時),添加等等。下面的文章中,就進行重構這些功能!

 1. 顯示內容定制:list_display

2. 過濾功能 list_filter

 

3. 搜索功能 search_fields

4. 字段搜索功能 raw_id_fields

 

5. 字段過濾功能  filter_horizontal

6. 可編輯字段 list_editable

 




免責聲明!

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



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