一:创建项目名称,并且配置好数据库
二:数据模型场景
1 设计模型类; 2 # 模拟整个业务流程 3 1.确认整个过程中所要涉及的角色:销售,学生,教师,管理员等; 4 # Role; 5 2.每个角色对应着多个用户,用户可能也对应多个角色,比如:教师也担任管理员的角色; 6 # UserProfile(ManyToMany,Role); 7 3.客户报名学习,需要填写客户信息; 8 # CustomerInfo; 9 # 需要填写的信息包括: 10 # 姓名,联系方式,来源(转介绍,转介绍人),咨询人,客户状态,咨询时间; 11 4.如果成功报名,需要录入学员表; 12 # Students; 13 # :需要填写学员名称(从客户表中取ForeignKey) 14 # :需要填写所在班级(班级对应着课程信息,校区信息) 15 # ClassInfo;<<--Course,Branch; 16 # :班级类型,学期,任课教师(从用户中取),开班日期,毕业日期; 17 # Course:课程名,学费,周期,大纲; 18 # Branch:校区名,地址; 19 5.如果没有报名,需要对这类客户做一个跟踪记录; 20 # CustomerInfo; 21 # 需要记录的信息包括: 22 # 客户(客户表中取),跟踪信息,跟踪人(用户表中取),客户报名状态,填写时间; 23 6.在课期间,需要有上课的记录,以及学员作业成绩/考勤等记录; 24 # CourseRecord:上课记录 25 # :所在班级(在班级表中取),课程节次,上课教师(用户表中取),本节主题,本节内容,是否有作业,作业需求,记录日期; 26 # StudyRecord:学习记录 27 # :课程,学员,分数等级,成绩备注,考勤状况,记录时间;
三:设计数据库
1 from django.db import models 2 from django.contrib.auth.models import User #使用Django内置的用户表 3 4 # Create your models here. 5 6 class UserProfile(models.Model): 7 """ 8 用户信息表 9 """ 10 user = models.OneToOneField(User,on_delete=models.CASCADE) #创建外键,关联django用户表 11 #扩展用户字段 12 name = models.CharField(max_length=64,verbose_name="姓名") 13 role = models.ManyToManyField("Role",blank=True) # 双向一对多==多对多 14 15 def __str__(self): #__unicode__ python2.7版本 16 return self.name 17 class Meta: 18 verbose_name_plural = "用户信息" 19 20 class Role(models.Model): 21 """ 22 角色表 23 """ 24 name = models.CharField(max_length=64,unique=True) # 角色名不可以重复 25 menus = models.ManyToManyField("Menus",blank=True) 26 27 def __str__(self): 28 return self.name 29 class Meta: 30 verbose_name_plural = "角色" 31 32 class Student(models.Model): 33 """ 34 学员表 35 """ 36 customer = models.ForeignKey("CustomerInfo",on_delete=models.CASCADE) 37 class_grades = models.ManyToManyField("ClassList") 38 def __str__(self): 39 return self.customer 40 class Meta: 41 verbose_name = "学员表" 42 verbose_name_plural = "学员表" 43 44 class CustomerInfo(models.Model): 45 """ 46 客户信息表 47 """ 48 name = models.CharField(max_length=64,default=None) # 首次报名可能不知道名字 49 contact_type_choices = ((0,'qq'), 50 (1,'微信'), 51 (2,'手机号'), 52 ) 53 contact_type = models.SmallIntegerField(choices=contact_type_choices,default=0) 54 contact = models.CharField(max_length=64,unique=True) 55 source_choices = ((0,'QQ群'), 56 (1,'51CTO'), 57 (2,'百度推广'), 58 (3,'知乎'), 59 (4,'转介绍'), 60 (5,'其他'), 61 ) 62 source = models.SmallIntegerField(choices=source_choices) 63 referral_from = models.ForeignKey("self",blank=True,null=True,verbose_name="转介绍",on_delete=models.CASCADE) 64 consult_courses = models.ManyToManyField("Course",verbose_name="咨询课程") 65 consult_content = models.TextField(verbose_name="咨询内容") 66 status_choices = ((0,'未报名'), 67 (1,'已报名'), 68 (2,'已退学') 69 ) 70 status = models.SmallIntegerField(choices=status_choices) 71 consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE) 72 date = models.DateField(auto_now_add=True) 73 74 def __str__(self): 75 return self.name 76 class Meta: 77 verbose_name = "客户表" 78 verbose_name_plural = "客户表" 79 80 class CustomerFollowUp(models.Model): 81 """ 82 客户跟踪记录表 83 """ 84 customer = models.ForeignKey("CustomerInfo",on_delete=models.CASCADE) 85 content = models.TextField(verbose_name="跟踪内容") 86 user = models.ForeignKey("UserProfile",verbose_name="跟进人",on_delete=models.CASCADE) 87 status_choices = ((0,'近期无报名计划'), 88 (1, '一个月内报名'), 89 (2, '两周内报名'), 90 (3, '已报名'), 91 ) 92 status = models.SmallIntegerField(choices=status_choices) 93 date = models.DateField(auto_now_add=True) 94 def __str__(self): 95 return self.content 96 class Meta: 97 verbose_name = "客户追踪" 98 verbose_name_plural = "客户追踪" 99 100 class Course(models.Model): 101 """ 102 课程表 103 """ 104 name = models.CharField(verbose_name='课程名称',max_length=64,unique=True) 105 price = models.PositiveSmallIntegerField() 106 period = models.PositiveSmallIntegerField(verbose_name="课程周期(月)",default=5) 107 outline = models.TextField(verbose_name="大纲") 108 109 def __str__(self): 110 return self.name 111 class Meta: 112 verbose_name = "课程表" 113 verbose_name_plural = "课程表" 114 115 class ClassList(models.Model): 116 """ 117 班级列表 118 """ 119 branchschool = models.ForeignKey("BranchSchool",on_delete=models.CASCADE) 120 course = models.ForeignKey("Course",on_delete=models.CASCADE) 121 class_type_choices = ((0,'脱产'), 122 (1,'周末'), 123 (2,'网络班'), 124 ) 125 class_type = models.SmallIntegerField(choices=class_type_choices,default=0) 126 semester = models.SmallIntegerField(verbose_name="学期") 127 teachers = models.ManyToManyField("UserProfile",verbose_name="讲师") 128 start_date = models.DateField("开班日期") 129 graduate_date = models.DateField("毕业日期",blank=True,null=True) 130 131 def __str__(self): 132 return "%s(%s)期" %(self.course.name,self.semester) 133 134 class Meta: 135 """联合唯一""" 136 unique_together = [ 137 ('branchschool','class_type','course','semester') 138 ] 139 verbose_name = "班级" 140 verbose_name_plural = "班级" 141 142 class CourseRecord(models.Model): 143 """ 144 上课记录表 145 """ 146 class_grade = models.ForeignKey("ClassList",verbose_name="上课班级",on_delete=models.CASCADE) 147 day_num = models.PositiveSmallIntegerField(verbose_name="课程节次") 148 teacher = models.ForeignKey("UserProfile",on_delete=models.CASCADE) 149 title = models.CharField("本节主题",max_length=64) 150 content = models.TextField("本节内容") 151 has_homework = models.BooleanField("本节有作业",default=True) 152 homework = models.TextField("作业需求",blank=True,null=True) 153 date = models.DateTimeField(auto_now_add=True) 154 155 def __str__(self): 156 return "%s第(%s)节" %(self.class_grade,self.day_num) 157 class Meta: 158 unique_together = [ 159 ('class_grade','day_num') 160 ] 161 verbose_name_plural = "上课记录" 162 163 class StudyRecord(models.Model): 164 """ 165 学习记录表 166 """ 167 course_record = models.ForeignKey("CourseRecord",on_delete=models.CASCADE) 168 student = models.ForeignKey("Student",on_delete=models.CASCADE) 169 score_choices = ((100,"A+"), 170 (90,"A"), 171 (85,"B+"), 172 (80,"B"), 173 (75,"B-"), 174 (70,"C+"), 175 (60,"C"), 176 (40,"C-"), 177 (-50,"D"), 178 (0,"N/A"), #not avaliable 179 (-100,"COPY"), #not avaliable 180 ) 181 score = models.SmallIntegerField(choices=score_choices,default=0) 182 show_choices = ((0,'缺勤'), 183 (1,'已迟到'), 184 (2,'迟到'), 185 (3,'早退'), 186 ) 187 show_status = models.SmallIntegerField(choices=show_choices,default=1) 188 note = models.TextField("成绩备注",blank=True,null=True) 189 date = models.DateTimeField(auto_now_add=True) 190 191 def __str__(self): 192 return "%s %s %s" %(self.course_record,self.student,self.score) 193 class Meta: 194 unique_together = ('course_record','student') 195 verbose_name_plural = "学习记录" 196 197 class BranchSchool(models.Model): 198 """ 199 校区 200 """ 201 name = models.CharField(max_length=64,unique=True) 202 addr = models.CharField(max_length=128,blank=True,null=True) 203 def __str__(self): 204 return self.name 205 class Meta: 206 verbose_name = "校区" 207 verbose_name_plural = "校区" 208 209 class Menus(models.Model): 210 """ 211 动态菜单 212 """ 213 name = models.CharField(max_length=64) 214 url_type_choices = ((0,'absolute'), 215 (1,'dynamic'), 216 ) 217 url_type = models.SmallIntegerField(choices=url_type_choices) 218 url_name = models.CharField(max_length=128) 219 220 def __str__(self): 221 return self.name 222 class Meat: 223 unique_together = ('name','url_name') 224 verbose_name_plural = "菜单栏" 225 # 角色与菜单多对多关系,在Role表中添加关联
四:注册数据表
1 from django.contrib import admin 2 from crm import models 3 4 # Register your models here. 5 6 admin.site.register(models.UserProfile) 7 admin.site.register(models.Role) 8 admin.site.register(models.Student) 9 admin.site.register(models.CustomerInfo) 10 admin.site.register(models.CustomerFollowUp) 11 admin.site.register(models.Course) 12 admin.site.register(models.ClassList) 13 admin.site.register(models.CourseRecord) 14 admin.site.register(models.StudyRecord) 15 admin.site.register(models.BranchSchool) 16 admin.site.register(models.Menus)
五:生成数据表并创建管理员账户
1 python manage.py makemigrations 2 python manage.py migrate 3 4 创建管理员用户 5 6 python manage.py createsuperuser
为啥我的后台页面和原生的admin后台管理页面不一样,因为我美化了后台只需要在settings做以下几步就可以搞定
1 INSTALLED_APPS = [ 2 'suit', 3 'django.contrib.admin', 4 'django.contrib.auth', 5 'django.contrib.contenttypes', 6 'django.contrib.sessions', 7 'django.contrib.messages', 8 'django.contrib.staticfiles', 9 'crm.apps.CrmConfig', 10 ] 11 12 13 14 LANGUAGE_CODE = 'zh-Hans' 15 16 TIME_ZONE = 'Asia/Shanghai' 17 18 USE_I18N = True 19 20 USE_L10N = False 21 22 USE_TZ = True 23 24 DATETIME_FORMAT = 'Y-m-d H:i:s' 25 DATE_FORMAT = 'Y-m-d' 26 27 SUIT_CONFIG = { 28 'ADMIN_NAME': 'CRM管理系统', 29 'MENU': ( 30 'sites', 31 {'app': 'accounts', 'label': '帐户'}, 32 {'app': 'zinnia', 'label': '博客'}, 33 {'app': 'auth', 'label': '认证管理'}, 34 ), 35 } 36 37 38 # Static files (CSS, JavaScript, Images) 39 # https://docs.djangoproject.com/en/2.0/howto/static-files/ 40 41 STATIC_URL = '/static/' 42 STATICFILES_DIRS = ( 43 os.path.join(BASE_DIR,'statics'), 44 )