1 #models.py 2 3 # ————————01PerfectCRM基本配置ADMIN———————— 4 5 from django.db import models 6 # Create your models here. 7 8 """ 9 #运行 Terminal 10 # 生成 数据表 11 # python manage.py makemigrations 12 # 数据表 迁移 13 # python manage.py migrate 14 """ 15 16 """01校区表""" 17 class Branch(models.Model): 18 name = models.CharField(max_length=128,unique=True) #校区名#CharField作用是保存文本,定长的变量类型 19 addr = models.CharField(max_length=128) #地址 20 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 21 return self.name #返回 #校区名 22 class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据 23 verbose_name_plural = "01校区表" #verbose_name_plural给你的模型类起一个更可读的名字 24 25 """02班级表""" 26 class ClassList(models.Model): 27 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 28 branch = models.ForeignKey("Branch",on_delete=models.CASCADE)#校区 关联到 校区表 29 course = models.ForeignKey("Course",on_delete=models.CASCADE) #课程 关联到 课程表 30 31 class_type_choices = ( #上课形式 32 (0,'面授(脱产)'), 33 (1,'面授(周末)'), 34 (2,'网络班'),) 35 #PositiveSmallIntegerField正小整数 0 ~ 32767 #choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 36 class_type = models.SmallIntegerField(choices=class_type_choices)#上课形式 37 38 #PositiveSmallIntegerField正小整数 0 ~ 32767 39 semester = models.PositiveSmallIntegerField(verbose_name="学期") #课程的第几期 40 41 #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。 42 teachers = models.ManyToManyField("UserProfile") # 老师 关联到 账号表 43 44 start_date = models.DateField(verbose_name="开班日期") #DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称 45 46 # DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称 #Django可空#数据库可以为空 47 end_date = models.DateField(verbose_name="结业日期",blank=True,null=True) 48 49 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 50 return "%s %s %s" %(self.branch,self.course,self.semester) #返回 #%s格式化输出字符串 #校区#课程# 学期 51 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 52 unique_together=('branch','course','semester') #联合索引 53 verbose_name_plural = "02班级表" #verbose_name_plural给你的模型类起一个更可读的名字 54 55 """03课程表,可以报名那些课程""" 56 class Course(models.Model): 57 name = models.CharField(max_length=64,unique=True)#课程名 #CharField作用是保存文本,定长的变量类型 58 price = models.PositiveSmallIntegerField(verbose_name="学费")#学费#PositiveSmallIntegerField正小整数 0 ~ 32767 59 period = models.PositiveSmallIntegerField(verbose_name="周期(月)") #PositiveSmallIntegerField正小整数 0 ~ 32767 60 outline = models.TextField() #课程大纲 #文本类型 61 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 62 return self.name #返回 #课程名 63 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 64 verbose_name_plural = "03课程表"#verbose_name_plural给你的模型类起一个更可读的名字 65 66 '''04客户信息表''' 67 class Customer(models.Model): 68 name = models.CharField(max_length=32,blank=True,null=True)#客户名#CharField定长文本 #名字最长32 # Django可空 #数据库可以为空 69 qq = models.CharField(max_length=64,unique=True) #QQ号#CharField定长文本 #名字最长64 #唯一,不能重复 70 qq_name = models.CharField(max_length=64,blank=True,null=True)#QQ名 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空 71 phone = models.CharField(max_length=64,blank=True,null=True)#手机号 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空 72 73 source_choices = ( #客户渠道来源 (内存生成) 74 (0,'转介绍'), 75 (1,'QQ群'), 76 (2,'官网'), 77 (3,'百度推广'), 78 (4,'51CTO'), 79 (5,'知乎'), 80 (6,'市场推广'),) 81 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 82 source = models.SmallIntegerField(choices=source_choices)#客户渠道来源 83 84 #CharField定长文本#verbose_name是Admin中显示的字段名称#名字最长64 # Django可空 #数据库可以为空 85 referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True) #来自谁介绍的 86 87 #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 88 consult_courses = models.ForeignKey("Course",verbose_name="咨询课程", on_delete=models.CASCADE) #关联到 课程表 89 90 content= models.TextField(verbose_name="咨询详情") #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称 91 92 #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。 93 tags = models.ManyToManyField("Tag",blank=True)#多对多关联到 标签表 94 95 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 96 consultant = models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到 账号表 97 98 memo = models.TextField(blank=True,null=True)#备注#TextField无限制长度的文本#Django可空#数据库可以为空 99 100 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读) 101 date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) 102 103 def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 104 return self.qq #返回 #QQ号 105 106 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 107 verbose_name_plural = "04客户表" #verbose_name_plural给你的模型类起一个更可读的名字 108 109 """05客户跟进表""" 110 class CustomerFollowUp(models.Model): 111 112 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 113 customer = models.ForeignKey("Customer", on_delete=models.CASCADE)#客户名 #关联到 客户信息表 114 115 content = models.TextField(verbose_name="跟进内容")#跟进的内容#TextField无限制长度的文本#verbose_name是Admin中显示的字段名称 116 117 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 118 consultant =models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到 账号表 119 120 intention_choices =( #报名状态 121 (0,'2周内报名'), 122 (1,'1个月内报名'), 123 (2,'近期无报名计划'), 124 (3,'已在其它机构报名'), 125 (4,'已报名'), 126 (5,'已拉黑'),) 127 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 128 intention=models.SmallIntegerField(choices=intention_choices) #报名状态 129 130 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读) 131 date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) 132 133 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 134 return "<%s:%s>" %(self.customer.qq,self.intention) #返回#格式化字符串#跨表里的QQ号#报名状态 135 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 136 verbose_name_plural = "05客户跟进表"#verbose_name_plural给你的模型类起一个更可读的名字 137 138 """06学员报名信息表""" 139 class Enrollment(models.Model): 140 # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 141 customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 #关联到 客户信息表 142 enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级",on_delete=models.CASCADE)#关联到 班级表 143 consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE) #关联到 账号表 144 145 #BooleanField布尔值类型#default=False默认(True)不允许出现空字符#verbose_name是Admin中显示的字段名称 146 contract_agreed = models.BooleanField(default=False,verbose_name="学员已经同意合同")#学员看合同 147 contract_approved = models.BooleanField(default=False,verbose_name="合同已经审核") #谁审核 148 149 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读) 150 date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) 151 152 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 153 return "%s %s" %(self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级 154 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 155 unique_together = ("customer","enrolled_class")#联合索引 156 verbose_name_plural = "06学员报名信息表"#verbose_name_plural给你的模型类起一个更可读的名字 157 158 """07缴费记录表""" 159 class Payment(models.Model): 160 #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 161 customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 关联到 客户信息表 162 course = models.ForeignKey("Course",verbose_name="所报课程",on_delete=models.CASCADE)#关联到 课程表 163 164 #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称#默认值=500 165 amount = models.PositiveIntegerField(verbose_name="数额",default=500)#缴费数额 166 167 #ForeignKey就是表与表之间的某种约定的关系#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 168 consultant = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#缴费给谁 关联到 账号表 169 170 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读) 171 date=models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) 172 173 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 174 return "%s %s" %(self.customer,self.amount)#返回#格式化字符串#学员名字#缴费数额 175 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 176 verbose_name_plural = "07缴费记录表"#verbose_name_plural给你的模型类起一个更可读的名字 177 178 """08每节课上课纪录表""" 179 class CourseRecord(models.Model): 180 # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 181 from_class = models.ForeignKey("ClassList",verbose_name="班级",on_delete=models.CASCADE) #那个班级 182 183 #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称 184 day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)") #第几节课 185 186 # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 187 teacher = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#老师是谁 关联到 账号表 188 189 #BooleanField布尔值类型#default=True默认(True)不允许出现空字符 190 has_homework = models.BooleanField(default=True) #有没有作业 191 192 # CharField定长文本#名字最长128#Django可空#数据库可以为空 193 homework_title = models.CharField(max_length=128,blank=True,null=True) #作业标题 194 195 #TextField无限制长度的文本#Django可空#数据库可以为空 196 homework_content = models.TextField(blank=True,null=True) #作业内容 197 198 #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称 199 outline =models.TextField(verbose_name="本节课程大纲") #课程主要讲什么 200 201 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读) 202 date = models.DateField(auto_now_add=True)#创建时间(数据库自增) 203 204 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 205 return " %s:%s" %(self.from_class,self.day_num)#返回#格式化字符串#班级#第几节(天) 206 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 207 unique_together = ("from_class","day_num") #联合索引 208 verbose_name_plural = "08每节课上课纪录表" #verbose_name_plural给你的模型类起一个更可读的名字 209 210 """09学习纪录""" 211 class StudyRecord(models.Model): 212 # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 213 student = models.ForeignKey("Enrollment",on_delete=models.CASCADE)#学生名字 关联到 学员报名信息表 214 course_record = models.ForeignKey("CourseRecord",on_delete=models.CASCADE)#开课记录 # 关联到 每节课上课纪录表 215 216 attendance_choices = (# 本节课上课状态记录 217 (0,"已签到"), 218 (1,"迟到"), 219 (2,"缺勤"), 220 (3,"早退"),) 221 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 222 attendance = models.SmallIntegerField(choices=attendance_choices) # 本节课上课状态记录 223 224 score_choices = (#学习成绩 225 (100,"A+"), 226 (90,"A"), 227 (85,"B+"), 228 (80,"B"), 229 (75,"B-"), 230 (70,"C+"), 231 (65,"C"), 232 (40,"C-"), 233 (-20,"D"), 234 (-50,"COPY"), 235 (0,"N/A"),) 236 #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 237 score = models.SmallIntegerField(choices=score_choices) #学习成绩 238 239 memo = models.TextField(blank=True,null=True)#TextField无限制长度的文本#Django可空#数据库可以为空 240 241 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读) 242 date = models.DateField(auto_now_add=True)#创建时间(数据库自增) 243 244 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 245 return "%s %s %s" % (self.student, self.course_record, self.score)#返回#格式化字符串#学生名字#开课记录#学习成绩 246 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 247 unique_together = ('student','course_record')#联合索引#学生名字#开课记录 248 verbose_name_plural = "09学习纪录"#verbose_name_plural给你的模型类起一个更可读的名字 249 250 # ————————34PerfectCRM实现CRM自定义用户———————— 251 # """10账号表""" 252 # class UserProfile(models.Model): 253 # from django.contrib.auth.models import User # 使用django内置的用户表 254 # 255 # #OneToOneField一对一 #User是django Admin里的账号表#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。 256 # user = models.OneToOneField(User,on_delete=models.CASCADE)# 用户名 #创建外键,关联django用户表 257 # 258 # name = models.CharField(max_length=32) #账号名(扩展用户字段)#CharField定长文本 259 # 260 # #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。#Django可空 261 # roles = models.ManyToManyField("Role",blank=True) #角色(权限) # 双向一对多==多对多 262 # 263 # def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 264 # return self.name #返回 #账号名 265 # class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据 266 # verbose_name_plural = "10账号表"#verbose_name_plural给你的模型类起一个更可读的名字 267 # ————————34PerfectCRM实现CRM自定义用户———————— 268 269 # ————————34PerfectCRM实现CRM自定义用户———————— 270 #10账号表,创建用户和超级用户 271 from django.contrib.auth.models import BaseUserManager 272 class UserProfileManager(BaseUserManager): 273 def create_user(self, email, name, password=None): 274 """ 275 创建并保存一个用户用给定的邮件,日期 276 出生和密码。 277 """ 278 if not email:#没有email 报错 279 raise ValueError('用户必须有一个电子邮件地址') 280 281 user = self.model( 282 email=self.normalize_email(email),#验证邮箱格式 283 name=name, 284 ) 285 user.set_password(password)#加密 286 user.is_active = True 287 user.save(using=self._db) 288 return user 289 def create_superuser(self, email, name, password): 290 """ 291 创建并保存一个超级用户具有给定邮件,日期 292 出生和密码。 293 """ 294 user = self.create_user(email, 295 password=password, 296 name=name 297 ) 298 user.is_active = True 299 user.is_superuser = True 300 user.save(using=self._db) 301 return user 302 303 """10账号表""" 304 """ 305 306 #删除数据库 307 308 #调用objects = UserProfileManager()#创建账号 #关联这个函数 309 310 #运行 Terminal 311 # 生成 数据表 312 # python manage.py makemigrations 313 # 数据表 迁移 314 # python manage.py migrate 315 Django Admin里账号密码重置方法 316 #运行 Terminal 317 python manage.py createsuperuser 318 319 Email address: admin@qq.com 320 用户名 : admin 321 Password: admin123456 322 Password (again): admin123456 323 """ 324 from django.contrib.auth.models import AbstractBaseUser 325 class UserProfile(AbstractBaseUser): 326 email=models.EmailField( 327 verbose_name='邮箱账号', 328 max_length=255, 329 unique=True#唯一 #登陆账号 330 ) 331 name=models.CharField(max_length=32,verbose_name='用户名') 332 is_active = models.BooleanField(default=True,verbose_name='合法账号')#权限#合法账号 333 is_superuser = models.BooleanField(default=False,verbose_name='超级账号') #超级账号 334 objects = UserProfileManager()#创建账号 #关联这个函数 335 USERNAME_FIELD ='email'#指定做为 #登陆账号 336 REQUIRED_FIELDS = ['name']#必填字段 337 def get_full_name(self): 338 return self.email 339 def get_short_name(self): 340 #用户确认的电子邮件地址 341 return self.email 342 def __str__(self): 343 return self.name 344 def has_perm(self,perm,obj=None): 345 #指明用户是否被认为活跃的。以反选代替删除帐号。 346 #最简单的可能的答案:是的,总是 347 return True #有效 账号 348 def has_module_perms(self, app_label): 349 #指明用户是否可以登录到这个管理站点。 350 # 最简单的可能的答案:是的,总是 351 return True #职员状态 352 @property 353 def is_staff(self): 354 '''“用户的员工吗?”''' 355 #最简单的可能的答案:所有管理员都是员工 356 return self.is_superuser#是不是超级用户状态 357 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单 #settings.py 358 # ————————34PerfectCRM实现CRM自定义用户———————— 359 360 """11角色表""" 361 class Role(models.Model): 362 name = models.CharField(unique=True,max_length=32)#角色名#CharField定长文本#角色名不可以重复#最长度=32字节 363 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 364 return self.name#返回 #角色名 365 class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据 366 verbose_name_plural = "11角色表" #verbose_name_plural给你的模型类起一个更可读的名字 367 368 """12标签表""" 369 class Tag(models.Model): 370 name = models.CharField(max_length=64,unique=True) #标签名#CharField定长文本#最长度=64字节#不可以重复 371 def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 372 return self.name #返回 #标签名 373 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 374 verbose_name_plural = "12标签表" #verbose_name_plural给你的模型类起一个更可读的名字 375 376 # ————————01PerfectCRM基本配置ADMIN————————