项目一:CRM(客户关系管理系统)--1
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