Django
的admin
已經為我們做好了,很完善的后台管理體系,但頁面過於丑陋,自定義的能力還是有局限性的。特此,重寫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思維導圖:
數據關系圖:
在主app
,CRM
中的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