zoukankan      html  css  js  c++  java
  • Django项目:CRM(客户关系管理系统)--84--74PerfectCRM实现CRM权限和权限组限制访问URL

      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     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
     32     contract = models.ForeignKey('ContractTemplate', blank=True, null=True, default=1,on_delete=models.CASCADE)  # 合同表
     33     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
     34 
     35     class_type_choices = ( #上课形式
     36                           (0,'面授(脱产)'),
     37                           (1,'面授(周末)'),
     38                           (2,'网络班'),)
     39     #PositiveSmallIntegerField正小整数 0 ~ 32767 #choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
     40     class_type = models.SmallIntegerField(choices=class_type_choices)#上课形式
     41 
     42     #PositiveSmallIntegerField正小整数 0 ~ 32767
     43     semester = models.PositiveSmallIntegerField(verbose_name="学期") #课程的第几期
     44 
     45     #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
     46     teachers = models.ManyToManyField("UserProfile") # 老师   关联到    账号表
     47 
     48     start_date = models.DateField(verbose_name="开班日期") #DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称
     49 
     50     # DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称 #Django可空#数据库可以为空
     51     end_date = models.DateField(verbose_name="结业日期",blank=True,null=True)
     52 
     53     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
     54         return "%s %s %s" %(self.branch,self.course,self.semester) #返回 #%s格式化输出字符串 #校区#课程# 学期
     55     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
     56         unique_together=('branch','course','semester')  #联合索引
     57         verbose_name_plural = "02班级表" #verbose_name_plural给你的模型类起一个更可读的名字
     58 
     59 """03课程表,可以报名那些课程"""
     60 class Course(models.Model):
     61     name = models.CharField(max_length=64,unique=True)#课程名 #CharField作用是保存文本,定长的变量类型
     62     price = models.PositiveSmallIntegerField(verbose_name="学费")#学费#PositiveSmallIntegerField正小整数 0 ~ 32767
     63     period = models.PositiveSmallIntegerField(verbose_name="周期(月)") #PositiveSmallIntegerField正小整数 0 ~ 32767
     64     outline = models.TextField() #课程大纲  #文本类型
     65     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
     66         return self.name #返回 #课程名
     67     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
     68         verbose_name_plural =  "03课程表"#verbose_name_plural给你的模型类起一个更可读的名字
     69 
     70 '''04客户信息表'''
     71 class Customer(models.Model):
     72     name = models.CharField(max_length=32,blank=True,null=True)#客户名#CharField定长文本 #名字最长32 # Django可空 #数据库可以为空
     73     qq = models.CharField(max_length=64,unique=True) #QQ号#CharField定长文本 #名字最长64 #唯一,不能重复
     74     qq_name = models.CharField(max_length=64,blank=True,null=True)#QQ名 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空
     75     phone = models.CharField(max_length=64,blank=True,null=True)#手机号 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空
     76 
     77     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
     78     id_num=models.CharField(max_length=64,blank=True,null=True,verbose_name='身份证号')#身份证号
     79     email=models.EmailField(max_length=64,blank=True,null=True,verbose_name='邮箱')#email
     80     sex_choices=((0,'保密'),(1,''),(2,''))
     81     sex=models.SmallIntegerField(choices=sex_choices,default=0,verbose_name='性别')
     82     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
     83 
     84     # ————————53PerfectCRM实现CRM客户报名流程缴费————————
     85     status_choices = ((0, '已报名'), (1, '未报名'), (2, '已退学'))
     86     status = models.SmallIntegerField(choices=status_choices, default=1)  # 学员状态
     87     # ————————53PerfectCRM实现CRM客户报名流程缴费————————
     88 
     89     source_choices = ( #客户渠道来源 (内存生成)
     90                       (0,'转介绍'),
     91                       (1,'QQ群'),
     92                       (2,'官网'),
     93                       (3,'百度推广'),
     94                       (4,'51CTO'),
     95                       (5,'知乎'),
     96                       (6,'市场推广'),)
     97     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
     98     source = models.SmallIntegerField(choices=source_choices)#客户渠道来源
     99 
    100     #CharField定长文本#verbose_name是Admin中显示的字段名称#名字最长64 # Django可空 #数据库可以为空
    101     referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True) #来自谁介绍的
    102 
    103     #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    104     consult_courses = models.ForeignKey("Course",verbose_name="咨询课程", on_delete=models.CASCADE) #关联到 课程表
    105 
    106     content= models.TextField(verbose_name="咨询详情") #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
    107 
    108     #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
    109     tags = models.ManyToManyField("Tag",blank=True)#多对多关联到 标签表
    110 
    111     #ForeignKey就是表与表之间的某种约定的关系  #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    112     consultant = models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到  账号表
    113 
    114     memo = models.TextField(blank=True,null=True)#备注#TextField无限制长度的文本#Django可空#数据库可以为空
    115 
    116     #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
    117     date =  models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
    118 
    119     def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    120         return self.qq  #返回 #QQ号
    121 
    122     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    123         verbose_name_plural =  "04客户表" #verbose_name_plural给你的模型类起一个更可读的名字
    124 
    125 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
    126 #合同模版
    127 class ContractTemplate(models.Model):
    128     name=models.CharField('合同名称',max_length=64,unique=True)
    129     template=models.TextField()
    130 
    131     def __str__(self):
    132         return self.name
    133     class Meta:
    134         verbose_name_plural='合同表'
    135 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
    136 
    137 
    138 """05客户跟进表"""
    139 class CustomerFollowUp(models.Model):
    140 
    141     #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    142     customer = models.ForeignKey("Customer", on_delete=models.CASCADE)#客户名 #关联到  客户信息表
    143 
    144     content = models.TextField(verbose_name="跟进内容")#跟进的内容#TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
    145 
    146     #ForeignKey就是表与表之间的某种约定的关系  #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    147     consultant =models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到  账号表
    148 
    149     intention_choices =(  #报名状态
    150                         (0,'2周内报名'),
    151                         (1,'1个月内报名'),
    152                         (2,'近期无报名计划'),
    153                         (3,'已在其它机构报名'),
    154                         (4,'已报名'),
    155                         (5,'已拉黑'),)
    156     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
    157     intention=models.SmallIntegerField(choices=intention_choices) #报名状态
    158 
    159     #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
    160     date =  models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
    161 
    162     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    163         return "<%s:%s>" %(self.customer.qq,self.intention) #返回#格式化字符串#跨表里的QQ号#报名状态
    164     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    165         verbose_name_plural =  "05客户跟进表"#verbose_name_plural给你的模型类起一个更可读的名字
    166 
    167 """06学员报名信息表"""
    168 class Enrollment(models.Model):
    169     # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    170     customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 #关联到  客户信息表
    171     enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级",on_delete=models.CASCADE)#关联到  班级表
    172     consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE) #关联到  账号表
    173 
    174     # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
    175     contract_review = models.CharField(max_length=256, blank=True, null=True, verbose_name="合同审核")  # 合同审核
    176     # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
    177 
    178     #BooleanField布尔值类型#default=False默认(True)不允许出现空字符#verbose_name是Admin中显示的字段名称
    179     contract_agreed = models.BooleanField(default=False,verbose_name="学员已经同意合同")#学员看合同
    180     contract_approved = models.BooleanField(default=False,verbose_name="合同已经审核") #谁审核
    181 
    182     # ————————53PerfectCRM实现CRM客户报名流程缴费————————
    183     Pay_cost= models.BooleanField(default=False,verbose_name="缴费") #缴费状态#是不是交定金
    184     # ————————53PerfectCRM实现CRM客户报名流程缴费————————
    185 
    186     # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
    187     date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
    188 
    189     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    190         # ————————57PerfectCRM实现admin批量生成上课记录————————
    191         # return "%s %s" %(self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
    192         return " 学员:%s |QQ: %s |班级:%s" %(self.customer.name,self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
    193         # ————————57PerfectCRM实现admin批量生成上课记录————————
    194     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    195         unique_together =  ("customer","enrolled_class")#联合索引
    196         verbose_name_plural =  "06学员报名信息表"#verbose_name_plural给你的模型类起一个更可读的名字
    197 
    198 """07缴费记录表"""
    199 class Payment(models.Model):
    200     #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    201     customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字        关联到  客户信息表
    202     course = models.ForeignKey("Course",verbose_name="所报课程",on_delete=models.CASCADE)#关联到  课程表
    203 
    204     #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称#默认值=500
    205     amount = models.PositiveIntegerField(verbose_name="数额",default=500)#缴费数额
    206 
    207     #ForeignKey就是表与表之间的某种约定的关系#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    208     consultant = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#缴费给谁 关联到  账号表 #财务人员
    209 
    210     #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
    211     date=models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
    212 
    213     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    214         return "%s %s" %(self.customer,self.amount)#返回#格式化字符串#学员名字#缴费数额
    215     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    216         verbose_name_plural = "07缴费记录表"#verbose_name_plural给你的模型类起一个更可读的名字
    217 
    218 """08每节课上课纪录表"""
    219 class CourseRecord(models.Model):
    220     # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    221     from_class = models.ForeignKey("ClassList",verbose_name="班级",on_delete=models.CASCADE) #那个班级
    222 
    223     #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称
    224     day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)") #第几节课
    225 
    226     # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    227     teacher = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#老师是谁    关联到    账号表
    228 
    229     #BooleanField布尔值类型#default=True默认(True)不允许出现空字符
    230     has_homework = models.BooleanField(default=True) #有没有作业
    231 
    232     # CharField定长文本#名字最长128#Django可空#数据库可以为空
    233     homework_title = models.CharField(max_length=128,blank=True,null=True) #作业标题
    234 
    235     #TextField无限制长度的文本#Django可空#数据库可以为空
    236     homework_content = models.TextField(blank=True,null=True) #作业内容
    237 
    238     #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
    239     outline =models.TextField(verbose_name="本节课程大纲") #课程主要讲什么
    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" %(self.from_class,self.day_num)#返回#格式化字符串#班级#第几节(天)
    246     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    247         unique_together = ("from_class","day_num") #联合索引
    248         verbose_name_plural = "08每节课上课纪录表" #verbose_name_plural给你的模型类起一个更可读的名字
    249 
    250 """09学习纪录"""
    251 class StudyRecord(models.Model):
    252     # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    253     student = models.ForeignKey("Enrollment",on_delete=models.CASCADE)#学生名字   关联到    学员报名信息表
    254     course_record = models.ForeignKey("CourseRecord",on_delete=models.CASCADE)#开课记录   # 关联到    每节课上课纪录表
    255 
    256     attendance_choices = (# 本节课上课状态记录
    257                             (0,"已签到"),
    258                             (1,"迟到"),
    259                             (2,"缺勤"),
    260                             (3,"早退"),)
    261     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
    262     attendance = models.SmallIntegerField(choices=attendance_choices) # 本节课上课状态记录
    263 
    264     # ————————63PerfectCRM实现CRM讲师下载作业————————
    265     delivery = models.BooleanField(default=False,verbose_name="交作业") #有没有交付作业
    266     # ————————63PerfectCRM实现CRM讲师下载作业————————
    267 
    268 
    269     # ————————61PerfectCRM实现CRM学生上传作业————————
    270     homework_link = models.TextField(blank=True,null=True)#作业链接 #TextField无限制长度的文本#Django可空#数据库可以为空
    271     # ————————61PerfectCRM实现CRM学生上传作业————————
    272 
    273     score_choices = (#学习成绩
    274                      (100,"A+"),
    275                      (90,"A"),
    276                      (85,"B+"),
    277                      (80,"B"),
    278                      (75,"B-"),
    279                      (70,"C+"),
    280                      (65,"C"),
    281                      (40,"C-"),
    282                      (-20,"D"),
    283                      (-50,"COPY"),
    284                      (0,"N/A"),)
    285     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
    286     score = models.SmallIntegerField(choices=score_choices) #学习成绩
    287 
    288 
    289     memo = models.TextField(blank=True,null=True)#TextField无限制长度的文本#Django可空#数据库可以为空
    290 
    291     # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
    292     date = models.DateField(auto_now_add=True)#创建时间(数据库自增)
    293 
    294     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    295         return "%s %s %s" % (self.student, self.course_record, self.score)#返回#格式化字符串#学生名字#开课记录#学习成绩
    296     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    297         unique_together = ('student','course_record')#联合索引#学生名字#开课记录
    298         verbose_name_plural =  "09学习纪录"#verbose_name_plural给你的模型类起一个更可读的名字
    299 
    300 # ————————34PerfectCRM实现CRM自定义用户————————
    301 # """10账号表"""
    302 # class UserProfile(models.Model):
    303 #     from django.contrib.auth.models import User  # 使用django内置的用户表
    304 #
    305 #     #OneToOneField一对一  #User是django Admin里的账号表#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
    306 #     user = models.OneToOneField(User,on_delete=models.CASCADE)# 用户名 #创建外键,关联django用户表
    307 #
    308 #     name = models.CharField(max_length=32) #账号名(扩展用户字段)#CharField定长文本
    309 #
    310 #     #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。#Django可空
    311 #     roles = models.ManyToManyField("Role",blank=True) #角色(权限)   # 双向一对多==多对多
    312 #
    313 #     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    314 #         return self.name #返回 #账号名
    315 #     class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    316 #         verbose_name_plural = "10账号表"#verbose_name_plural给你的模型类起一个更可读的名字
    317 # ————————34PerfectCRM实现CRM自定义用户————————
    318 
    319 # ————————34PerfectCRM实现CRM自定义用户————————
    320 #10账号表,创建用户和超级用户
    321 from django.contrib.auth.models import BaseUserManager
    322 class UserProfileManager(BaseUserManager):
    323     def create_user(self, email, name, password=None):
    324         """
    325       创建并保存一个用户用给定的邮件,日期
    326       出生和密码。
    327         """
    328         if not email:#没有email 报错
    329             raise ValueError('用户必须有一个电子邮件地址')
    330 
    331         user = self.model(
    332             email=self.normalize_email(email),#验证邮箱格式
    333             name=name,
    334         )
    335         user.set_password(password)#加密
    336         user.is_active = True
    337         user.save(using=self._db)
    338         return user
    339     def create_superuser(self, email, name, password):
    340         """
    341       创建并保存一个超级用户具有给定邮件,日期
    342       出生和密码。
    343         """
    344         user = self.create_user(email,
    345             password=password,
    346             name=name
    347         )
    348         user.is_active = True
    349         user.is_superuser = True
    350         user.save(using=self._db)
    351         return user
    352 
    353 """10账号表"""
    354 """
    355 
    356 #删除数据库
    357 
    358 #调用objects = UserProfileManager()#创建账号 #关联这个函数
    359 
    360 #运行 Terminal
    361 #    生成 数据表
    362 #    python manage.py makemigrations
    363 #   数据表 迁移
    364 #    python manage.py migrate
    365 Django Admin里账号密码重置方法
    366 #运行 Terminal  
    367 python manage.py createsuperuser
    368 
    369 Email address:          admin@qq.com
    370 用户名 :                 admin
    371 Password:               admin123456
    372 Password (again):       admin123456
    373 """
    374 from django.contrib.auth.models import AbstractBaseUser
    375 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
    376 from django.utils.translation import ugettext_lazy as _  # 语言国际化
    377 from django.utils.safestring import mark_safe
    378 from django.contrib.auth.models import PermissionsMixin
    379 # class UserProfile(AbstractBaseUser):
    380 class UserProfile(AbstractBaseUser,PermissionsMixin):
    381 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
    382     email=models.EmailField(
    383         verbose_name='邮箱账号',
    384         max_length=255,
    385         unique=True#唯一  #登陆账号
    386     )
    387     name=models.CharField(max_length=32,verbose_name='用户名')
    388 
    389 
    390     # ————————72PerfectCRM实现CRM动态菜单和角色————————
    391     branch = models.ForeignKey( "Branch", verbose_name="所属校区", blank=True, null=True, on_delete=models.CASCADE )
    392     roles = models.ManyToManyField( 'Role', verbose_name="角色", blank=True )
    393     memo = models.TextField( blank=True, null=True, default=None, verbose_name="备注" )
    394     from django.utils import timezone
    395     date_joined = models.DateTimeField( verbose_name="创建时间", default=timezone.now )
    396     # ————————72PerfectCRM实现CRM动态菜单和角色————————
    397 
    398     # ————————35PerfectCRM实现CRM重写Admin密码修改————————
    399     password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href="../password/">修改密码</a>'''))
    400     # ————————35PerfectCRM实现CRM重写Admin密码修改————————
    401 
    402     is_active = models.BooleanField(default=True,verbose_name='合法账号')#权限#合法账号
    403     is_superuser = models.BooleanField(default=False,verbose_name='超级账号') #超级账号
    404     objects = UserProfileManager()#创建账号 #关联这个函数
    405     USERNAME_FIELD ='email'#指定做为  #登陆账号
    406     REQUIRED_FIELDS = ['name']#必填字段
    407 
    408 
    409     # ————————60PerfectCRM实现CRM学生上课记录————————
    410     stu_account = models.ForeignKey( "Customer", verbose_name='关联学员帐号', blank=True, null=True, on_delete=models.CASCADE,
    411                                      help_text='报名成功后创建关联帐户' )
    412     # ————————60PerfectCRM实现CRM学生上课记录————————
    413 
    414     def get_full_name(self):
    415         return self.email
    416     def get_short_name(self):
    417         #用户确认的电子邮件地址
    418         return self.email
    419     def __str__(self):
    420         return self.name
    421     def has_perm(self,perm,obj=None):
    422         #指明用户是否被认为活跃的。以反选代替删除帐号。
    423         #最简单的可能的答案:是的,总是
    424         return True   #有效 账号
    425     def has_module_perms(self, app_label):
    426         #指明用户是否可以登录到这个管理站点。
    427         # 最简单的可能的答案:是的,总是
    428         return True #职员状态
    429     @property
    430     def is_staff(self):
    431         '''“用户的员工吗?”'''
    432         #最简单的可能的答案:所有管理员都是员工
    433         return self.is_superuser#是不是超级用户状态
    434 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单   #settings.py
    435 # ————————34PerfectCRM实现CRM自定义用户————————
    436 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
    437     class Meta:
    438         verbose_name_plural = '10CRM账户表'
    439         permissions = (
    440             ('crm_010101_all_table_data_list_GET', '010101_全部查看数据_GET'),
    441             ('crm_010102_all_table_data_list_POST', '010102_全部查看数据_POST'),
    442             ('crm_010103_all_table_add_GET', '010103_全部添加数据_GET'),
    443             ('crm_010104_all_table_add_POST', '010104_全部添加数据_POST'),
    444             ('crm_010105_all_table_change_GET', '010105_全部修改数据_GET'),
    445             ('crm_010106_all_table_change_POST', '010106_全部修改数据_POST'),
    446             ('crm_010107_all_table_delete_GET', '010107_全部删除数据_GET'),
    447             ('crm_010108_all_table_delete_POST', '010108_全部删除数据_POST'),
    448             ('crm_010109_all_password_reset_GET', '010109_全部密码重置_GET'),
    449             ('crm_010110_all_password_reset_POST', '010110_全部密码重置_POST'),
    450 
    451             ('crm_010201_only_view_Branch_GET', '010201_只能查看校区表_GET'),
    452             ('crm_010202_only_view_Branch_POST', '010202_只能查看校区表_POST'),
    453             ('crm_010203_only_add_Branch_GET', '010203_只能添加校区表_GET'),
    454             ('crm_010204_only_add_Branch_POST', '010204_只能添加校区表_POST'),
    455             ('crm_010205_only_change_Branch_GET', '010205_只能修改校区表_GET'),
    456             ('crm_010206_only_change_Branch_POST', '010206_只能修改校区表_POST'),
    457             ('crm_010207_only_delete_Branch_GET', '010207_只能删除校区表_GET'),
    458             ('crm_010208_only_delete_Branch_POST', '010208_只能删除校区表_POST'),
    459 
    460             ('crm_010301_only_view_ClassList_GET', '010301_只能查看班级表_GET'),
    461             ('crm_010302_only_view_ClassList_POST', '010302_只能查看班级表_POST'),
    462             ('crm_010303_only_add_ClassList_GET', '010303_只能添加班级表_GET'),
    463             ('crm_010304_only_add_ClassList_POST', '010304_只能添加班级表_POST'),
    464             ('crm_010305_only_change_ClassList_GET', '010305_只能修改班级表_GET'),
    465             ('crm_010306_only_change_ClassList_POST', '010306_只能修改班级表_POST'),
    466             ('crm_010307_only_delete_ClassList_GET', '010307_只能删除班级表_GET'),
    467             ('crm_010308_only_delete_ClassList_POST', '010308_只能删除班级表_POST'),
    468 
    469             ('crm_010401_only_view_Course_GET', '010401_只能查看课程表_GET'),
    470             ('crm_010402_only_view_Course_POST', '010402_只能查看课程表_POST'),
    471             ('crm_010403_only_add_Course_GET', '010403_只能添加课程表_GET'),
    472             ('crm_010404_only_add_Course_POST', '010404_只能添加课程表_POST'),
    473             ('crm_010405_only_change_Course_GET', '010405_只能修改课程表_GET'),
    474             ('crm_010406_only_change_Course_POST', '010406_只能修改课程表_POST'),
    475             ('crm_010407_only_delete_Course_GET', '010407_只能删除课程表_GET'),
    476             ('crm_010408_only_delete_Course_POST', '010408_只能删除课程表_POST'),
    477 
    478             ('crm_010501_only_view_Customer_GET', '010501_只能查看客户表_GET'),
    479             ('crm_010502_only_view_Customer_POST', '010502_只能查看客户表_POST'),
    480             ('crm_010503_only_add_Customer_GET', '010503_只能添加客户表_GET'),
    481             ('crm_010504_only_add_Customer_POST', '010504_只能添加客户表_POST'),
    482             ('crm_010505_only_change_Customer_GET', '010505_只能修改客户表_GET'),
    483             ('crm_010506_only_change_Customer_POST', '010506_只能修改客户表_POST'),
    484             ('crm_010507_only_delete_Customer_GET', '010507_只能删除客户表_GET'),
    485             ('crm_010508_only_delete_Customer_POST', '010508_只能删除客户表_POST'),
    486 
    487             ('crm_010601_only_view_CustomerFollowUp_GET', '010601_只能查看跟进表_GET'),
    488             ('crm_010602_only_view_CustomerFollowUp_POST', '010602_只能查看跟进表_POST'),
    489             ('crm_010603_only_add_CustomerFollowUp_GET', '010603_只能添加跟进表_GET'),
    490             ('crm_010604_only_add_CustomerFollowUp_POST', '010604_只能添加跟进表_POST'),
    491             ('crm_010605_only_change_CustomerFollowUp_GET', '010605_只能修改跟进表_GET'),
    492             ('crm_010606_only_change_CustomerFollowUp_POST', '010606_只能修改跟进表_POST'),
    493             ('crm_010607_only_delete_CustomerFollowUp_GET', '010607_只能删除跟进表_GET'),
    494             ('crm_010608_only_delete_CustomerFollowUp_POST', '010608_只能删除跟进表_POST'),
    495 
    496             ('crm_010701_only_view_Enrollment_GET', '010701_只能查看报名表_GET'),
    497             ('crm_010702_only_view_Enrollment_POST', '010702_只能查看报名表_POST'),
    498             ('crm_010703_only_add_Enrollment_GET', '010703_只能添加报名表_GET'),
    499             ('crm_010704_only_add_Enrollment_POST', '010704_只能添加报名表_POST'),
    500             ('crm_010705_only_change_Enrollment_GET', '010705_只能修改报名表_GET'),
    501             ('crm_010706_only_change_Enrollment_POST', '010706_只能修改报名表_POST'),
    502             ('crm_010707_only_delete_Enrollment_GET', '010707_只能删除报名表_GET'),
    503             ('crm_010708_only_delete_Enrollment_POST', '010708_只能删除报名表_POST'),
    504 
    505             ('crm_010801_only_view_Payment_GET', '010801_只能查看缴费表_GET'),
    506             ('crm_010802_only_view_Payment_POST', '010802_只能查看缴费表_POST'),
    507             ('crm_010803_only_add_Payment_GET', '010803_只能添加缴费表_GET'),
    508             ('crm_010804_only_add_Payment_POST', '010804_只能添加缴费表_POST'),
    509             ('crm_010805_only_change_Payment_GET', '010805_只能修改缴费表_GET'),
    510             ('crm_010806_only_change_Payment_POST', '010806_只能修改缴费表_POST'),
    511             ('crm_010807_only_delete_Payment_GET', '010807_只能删除缴费表_GET'),
    512             ('crm_010808_only_delete_Payment_POST', '010808_只能删除缴费表_POST'),
    513 
    514             ('crm_010901_only_view_CourseRecord_GET', '010901_只能查看上课表_GET'),
    515             ('crm_010902_only_view_CourseRecord_POST', '010902_只能查看上课表_POST'),
    516             ('crm_010903_only_add_CourseRecord_GET', '010903_只能添加上课表_GET'),
    517             ('crm_010904_only_add_CourseRecord_POST', '010904_只能添加上课表_POST'),
    518             ('crm_010905_only_change_CourseRecord_GET', '010905_只能修改上课表_GET'),
    519             ('crm_010906_only_change_CourseRecord_POST', '010906_只能修改上课表_POST'),
    520             ('crm_010907_only_delete_CourseRecord_GET', '010907_只能删除上课表_GET'),
    521             ('crm_010908_only_delete_CourseRecord_POST', '010908_只能删除上课表_POST'),
    522 
    523             ('crm_011001_only_view_StudyRecord_GET', '011001_只能查看学习表_GET'),
    524             ('crm_011002_only_view_StudyRecord_POST', '011002_只能查看学习表_POST'),
    525             ('crm_011003_only_add_StudyRecord_GET', '011003_只能添加学习表_GET'),
    526             ('crm_011004_only_add_StudyRecord_POST', '011004_只能添加学习表_POST'),
    527             ('crm_011005_only_change_StudyRecord_GET', '011005_只能修改学习表_GET'),
    528             ('crm_011006_only_change_StudyRecord_POST', '011006_只能修改学习表_POST'),
    529             ('crm_011007_only_delete_StudyRecord_GET', '011007_只能删除学习表_GET'),
    530             ('crm_011008_only_delete_StudyRecord_POST', '011008_只能删除学习表_POST'),
    531 
    532             ('crm_011101_only_view_UserProfile_GET', '011101_只能查看账号表_GET'),
    533             ('crm_011102_only_view_UserProfile_POST', '011102_只能查看账号表_POST'),
    534             ('crm_011103_only_add_UserProfile_GET', '011103_只能添加账号表_GET'),
    535             ('crm_011104_only_add_UserProfile_POST', '011104_只能添加账号表_POST'),
    536             ('crm_011105_only_change_UserProfile_GET', '011105_只能修改账号表_GET'),
    537             ('crm_011106_only_change_UserProfile_POST', '011106_只能修改账号表_POST'),
    538             ('crm_011107_only_delete_UserProfile_GET', '011107_只能删除账号表_GET'),
    539             ('crm_011108_only_delete_UserProfile_POST', '011108_只能删除账号表_POST'),
    540 
    541             ('crm_011201_only_view_Role_GET', '011201_只能查看角色表_GET'),
    542             ('crm_011202_only_view_Role_POST', '011202_只能查看角色表_POST'),
    543             ('crm_011203_only_add_Role_GET', '011203_只能添加角色表_GET'),
    544             ('crm_011204_only_add_Role_POST', '011204_只能添加角色表_POST'),
    545             ('crm_011205_only_change_Role_GET', '011205_只能修改角色表_GET'),
    546             ('crm_011206_only_change_Role_POST', '011206_只能修改角色表_POST'),
    547             ('crm_011207_only_delete_Role_GET', '011207_只能删除角色表_GET'),
    548             ('crm_011208_only_delete_Role_POST', '011208_只能删除角色表_POST'),
    549 
    550             ('crm_011301_only_view_Tag_GET', '011301_只能查看标签表_GET'),
    551             ('crm_011302_only_view_Tag_POST', '011302_只能查看标签表_POST'),
    552             ('crm_011303_only_add_Tag_GET', '011303_只能添加标签表_GET'),
    553             ('crm_011304_only_add_Tag_POST', '011304_只能添加标签表_POST'),
    554             ('crm_011305_only_change_Tag_GET', '011305_只能修改标签表_GET'),
    555             ('crm_011306_only_change_Tag_POST', '011306_只能修改标签表_POST'),
    556             ('crm_011307_only_delete_Tag_GET', '011307_只能删除标签表_GET'),
    557             ('crm_011308_only_delete_Tag_POST', '011308_只能删除标签表_POST'),
    558 
    559             ('crm_011401_only_view_FirstLayerMenu_GET', '011401_只能查看一层菜单_GET'),
    560             ('crm_011402_only_view_FirstLayerMenu_POST', '011402_只能查看一层菜单_POST'),
    561             ('crm_011403_only_add_FirstLayerMenu_GET', '011403_只能添加一层菜单_GET'),
    562             ('crm_011404_only_add_FirstLayerMenu_POST', '011404_只能添加一层菜单_POST'),
    563             ('crm_011405_only_change_FirstLayerMenu_GET', '011405_只能修改一层菜单_GET'),
    564             ('crm_011406_only_change_FirstLayerMenu_POST', '011406_只能修改一层菜单_POST'),
    565             ('crm_011407_only_delete_FirstLayerMenu_GET', '011407_只能删除一层菜单_GET'),
    566             ('crm_011408_only_delete_FirstLayerMenu_POST', '011408_只能删除一层菜单_POST'),
    567 
    568             ('crm_011501_only_view_SubMenu_GET', '011501_只能查看二层菜单_GET'),
    569             ('crm_011502_only_view_SubMenu_POST', '011502_只能查看二层菜单_POST'),
    570             ('crm_011503_only_add_SubMenu_GET', '011503_只能添加二层菜单_GET'),
    571             ('crm_011504_only_add_SubMenu_POST', '011504_只能添加二层菜单_POST'),
    572             ('crm_011505_only_change_SubMenu_GET', '011505_只能修改二层菜单_GET'),
    573             ('crm_011506_only_change_SubMenu_POST', '011506_只能修改二层菜单_POST'),
    574             ('crm_011507_only_delete_SubMenu_GET', '011507_只能删除二层菜单_GET'),
    575             ('crm_011508_only_delete_SubMenu_POST', '011508_只能删除二层菜单_POST'),
    576 
    577             ('crm_011601_only_view_Groups_GET', '011601_只能查看权限组_GET'),
    578             ('crm_011602_only_view_Groups_POST', '011602_只能查看权限组_POST'),
    579             ('crm_011603_only_add_Groups_GET', '011603_只能添加权限组_GET'),
    580             ('crm_011604_only_add_Groups_POST', '011604_只能添加权限组_POST'),
    581             ('crm_011605_only_change_Groups_GET', '011605_只能修改权限组_GET'),
    582             ('crm_011606_only_change_Groups_POST', '011606_只能修改权限组_POST'),
    583             ('crm_011607_only_delete_Groups_GET', '011607_只能删除权限组_GET'),
    584             ('crm_011608_only_delete_Groups_POST', '011608_只能删除权限组_POST'),
    585 
    586             ('crm_011701_own_password_reset_GET', '011701_自己密码重置_GET'),
    587             ('crm_011702_own_password_reset_POST', '011702_自己密码重置_POST'),
    588 
    589             ('crm_020101_all_not_audit_GET', '020101_销售查看全部的客户未审核_GET'),
    590             ('crm_020103_all_enrollment_GET', '020103_销售给全部的客户报名课程_GET'),
    591             ('crm_020104_all_enrollment_POST', '020104_销售给全部的客户报名课程_POST'),
    592             ('crm_020105_all_contract_review_GET', '020105_销售给全部的客户审核合同_GET'),
    593             ('crm_020116_all_contract_review_POST', '020116_销售给全部的客户审核合同_POST'),
    594 
    595             ('crm_020201_own_enrollment_GET', '020201_销售给自己的客户报名课程_GET'),
    596             ('crm_020202_own_enrollment_POST', '020202_销售给自己的客户报名课程_POST'),
    597             ('crm_020203_own_contract_review_GET', '020203_销售给自己的客户审核合同_GET'),
    598             ('crm_020204_own_contract_review_POST', '020204_销售给自己的客户审核合同_POST'),
    599 
    600             ('crm_030101_all_not_payment_GET', '030101_财务查看全部的客户未缴费_GET'),
    601             ('crm_030102_all_not_payment_POST', '030102_财务查看全部的客户未缴费_POST'),
    602             ('crm_030103_all_already_payment_GET', '030103_财务查看全部的客户已缴费_GET'),
    603             ('crm_030104_all_already_payment_POST', '030104_财务查看全部的客户已缴费_POST'),
    604             ('crm_030105_all_payment_GET', '030105_财务进行全部的客户缴费_GET'),
    605             ('crm_030106_all_payment_POST', '030106_财务进行全部的客户缴费_POST'),
    606 
    607             ('crm_040101_own_student_course_GET', '040101_学生查看自己的课程_GET'),
    608             ('crm_040102_own_student_course_POST', '040102_学生查看自己的课程_POST'),
    609             ('crm_040103_own_studyrecords_GET', '040103_学生自己的上课记录_GET'),
    610             ('crm_040104_own_studyrecords_POST', '040104_学生自己的上课记录_POST'),
    611             ('crm_040105_own_homework_detail_GET', '040105_学生自己的作业详情_GET'),
    612             ('crm_040106_own_homework_detail_POST', '040106_学生自己的作业详情_POST'),
    613 
    614             ('crm_050101_own_teacher_class_GET', '050101_讲师查看自己的班级_GET'),
    615             ('crm_050102_own_teacher_class_POST', '050102_讲师查看自己的班级_POST'),
    616             ('crm_050103_own_teacher_class_detail_GET', '050103_讲师查看自己的课节详情_GET'),
    617             ('crm_050104_own_teacher_class_detail_POST', '050104_讲师查看自己的课节详情_POST'),
    618             ('crm_050105_own_teacher_lesson_detail_GET', '050105_讲师查看自己的课节学员_GET'),
    619             ('crm_050106_own_teacher_lesson_detail_POST', '050106_讲师查看自己的课节学员_POST'),
    620             ('crm_050107_own_howk_down_GET', '050107_讲师自己的学员作业下载_GET'),
    621             ('crm_050108_own_howk_down_POST', '050108_讲师自己的学员作业下载_POST'),
    622 
    623             ('crm_060101_own_coursetop_details_GET', '060101_讲师查看自己的班级排名详情_GET'),
    624             ('crm_060102_own_coursetop_details_POST', '060102_讲师查看自己的班级排名详情_POST'),
    625             ('crm_060103_own_coursetop_score_GET', '060103_讲师查看自己的班级分数排行_GET'),
    626             ('crm_060104_own_coursetop_score_POST', '060104_讲师查看自己的班级排分数排行_POST'),
    627             ('crm_060105_own_coursetop_homework_GET', '060105_讲师查看自己的班级作业排行_GET'),
    628             ('crm_060106_own_coursetop_homework_POST', '060106_讲师查看自己的班级作业排行_POST'),
    629             ('crm_060107_own_coursetop_attendance_GET', '060107_讲师查看自己的班级出勤排行_GET'),
    630             ('crm_060108_own_coursetop_attendance_POST', '060108_讲师查看自己的班级出勤排行_POST'),
    631 
    632         )
    633 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
    634 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
    635 """15权限组"""
    636 from django.contrib.auth.models import Group
    637 class Groups(Group):
    638     class Meta:
    639         verbose_name_plural = '15权限组'
    640 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
    641 
    642 
    643 """11角色表"""
    644 class Role(models.Model):
    645     name = models.CharField(unique=True,max_length=32)#角色名#CharField定长文本#角色名不可以重复#最长度=32字节
    646 
    647     # ————————72PerfectCRM实现CRM动态菜单和角色————————
    648     menus = models.ManyToManyField('FirstLayerMenu',verbose_name='一层菜单',blank=True)
    649     # ————————72PerfectCRM实现CRM动态菜单和角色————————
    650 
    651     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    652         return self.name#返回 #角色名
    653     class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    654         verbose_name_plural = "11角色表" #verbose_name_plural给你的模型类起一个更可读的名字
    655 
    656 
    657 """12标签表"""
    658 class Tag(models.Model):
    659     name =  models.CharField(max_length=64,unique=True) #标签名#CharField定长文本#最长度=64字节#不可以重复
    660     def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
    661         return self.name #返回 #标签名
    662     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
    663         verbose_name_plural =  "12标签表" #verbose_name_plural给你的模型类起一个更可读的名字
    664 
    665 # ————————01PerfectCRM基本配置ADMIN————————
    666 
    667 
    668 # ————————72PerfectCRM实现CRM动态菜单和角色————————
    669 """13一层菜单名"""
    670 class FirstLayerMenu(models.Model):
    671     '''第一层侧边栏菜单'''
    672     name = models.CharField('一层菜单名',max_length=64)
    673     url_type_choices = ((0,'相关的名字'),(1,'固定的URL'))
    674     url_type = models.SmallIntegerField(choices=url_type_choices,default=0)
    675     url_name = models.CharField(max_length=64,verbose_name='一层菜单路径')
    676     order = models.SmallIntegerField(default=0,verbose_name='菜单排序')
    677     sub_menus = models.ManyToManyField('SubMenu',blank=True)
    678 
    679     def __str__(self):
    680         return self.name
    681 
    682     class Meta:
    683         verbose_name_plural = "13第一层菜单"
    684 
    685 """14二层菜单名"""
    686 class SubMenu(models.Model):
    687     '''第二层侧边栏菜单'''
    688     name = models.CharField('二层菜单名', max_length=64)
    689     url_type_choices = ((0,'相关的名字'),(1,'固定的URL'))
    690     url_type = models.SmallIntegerField(choices=url_type_choices,default=0)
    691     url_name = models.CharField(max_length=64, verbose_name='二层菜单路径')
    692     order = models.SmallIntegerField(default=0, verbose_name='菜单排序')
    693 
    694     def __str__(self):
    695         return self.name
    696 
    697     class Meta:
    698         verbose_name_plural = "14第二层菜单"
    699 # ————————72PerfectCRM实现CRM动态菜单和角色————————
    #models.py

      1 # permission_list.py
      2 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
      3 from permissions import CJ  # 自定义权限钩子
      4 
      5 # 权限样式 app_权限名字
      6 perm_dic = {
      7 
      8     'crm_010101_all_table_data_list_GET': ['table_data_list', 'GET', [], {}, ],
      9     # ('crm_010101_all_table_data_list_GET', '010101_全部查看数据_GET'),
     10     'crm_010102_all_table_data_list_POST': ['table_data_list', 'POST', [], {}, ],
     11     # ('crm_010102_all_table_data_list_POST', '010102_查全部看数据_POST'),
     12     'crm_010103_all_table_add_GET': ['table_add', 'GET', [], {}, ],
     13     # ('crm_010103_all_table_add_GET', '010103_全部添加数据_GET'),
     14     'crm_010104_all_table_add_POST': ['table_add', 'POST', [], {}, ],
     15     # ('crm_010104_all_table_add_POST', '010104_全部添加数据_POST'),
     16     'crm_010105_all_table_change_GET': ['table_change', 'GET', [], {}, ],
     17     # ('crm_010105_all_table_change_GET', '010105_全部修改数据_GET'),
     18     'crm_010106_all_table_change_POST': ['table_change', 'POST', [], {}, ],
     19     # ('crm_010106_all_table_change_POST', '010106_全部修改数据_POST'),
     20     'crm_010107_all_table_delete_GET': ['table_delete', 'GET', [], {}, ],
     21     # ('crm_010107_all_table_delete_GET', '010107_全部删除数据_GET'),
     22     'crm_010108_all_table_delete_POST': ['table_delete', 'POST', [], {}, ],
     23     # ('crm_010108_all_table_delete_POST', '010108_全部删除数据_POST'),
     24     'crm_010109_all_password_reset_GET': ['password_reset', 'GET', [], {}, ],
     25     # ('crm_010109_all_password_reset_GET', '010109_全部密码重置_GET'),
     26     'crm_010110_all_password_reset_POST': ['password_reset', 'POST', [], {}, ],
     27     # ('crm_010110_all_password_reset_POST', '010110_全部密码重置_POST'),
     28 
     29     'crm_010201_only_view_Branch_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Branch],
     30     # ('crm_010201_only_view_Branch_GET', '010201_只能查看校区表_GET'),
     31     'crm_010202_only_view_Branch_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Branch],
     32     # ('crm_010202_only_view_Branch_POST', '010202_只能查看校区表_POST'),
     33     'crm_010203_only_add_Branch_GET': ['table_add', 'GET', [], {}, CJ.JM_Branch],
     34     # ('crm_010203_only_add_Branch_GET', '010203_只能添加校区表_GET'),
     35     'crm_010204_only_add_Branch_POST': ['table_add', 'POST', [], {}, CJ.JM_Branch],
     36     # ('crm_010204_only_add_Branch_POST', '010204_只能添加校区表_POST'),
     37     'crm_010205_only_change_Branch_GET': ['table_change', 'GET', [], {}, CJ.JM_Branch],
     38     # ('crm_010205_only_change_Branch_GET', '010205_只能修改校区表_GET'),
     39     'crm_010206_only_change_Branch_POST': ['table_change', 'POST', [], {}, CJ.JM_Branch],
     40     #  ('crm_010206_only_change_Branch_POST', '010206_只能修改校区表_POST'),
     41     'crm_010207_only_delete_Branch_GET': ['table_delete', 'GET', [], {}, CJ.JM_Branch],
     42     # ('crm_010207_only_delete_Branch_GET', '010207_只能删除校区表_GET'),
     43     'crm_010208_only_delete_Branch_POST': ['table_delete', 'POST', [], {}, CJ.JM_Branch],
     44     # ('crm_010208_only_delete_Branch_POST', '010208_只能删除校区表_POST'),
     45 
     46     'crm_010301_only_view_ClassList_GET': ['table_data_list', 'GET', [], {}, CJ.JM_ClassList],
     47     # ('crm_010301_only_view_ClassList_GET', '010301_只能查看班级表_GET'),
     48     'crm_010302_only_view_ClassList_POST': ['table_data_list', 'POST', [], {}, CJ.JM_ClassList],
     49     # ('crm_010302_only_view_ClassList_POST', '010302_只能查看班级表_POST'),
     50     'crm_010303_only_add_ClassList_GET': ['table_add', 'GET', [], {}, CJ.JM_ClassList],
     51     # ('crm_010303_only_add_ClassList_GET', '010303_只能添加班级表_GET'),
     52     'crm_010304_only_add_ClassList_POST': ['table_add', 'POST', [], {}, CJ.JM_ClassList],
     53     # ('crm_010304_only_add_ClassList_POST', '010304_只能添加班级表_POST'),
     54     'crm_010305_only_change_ClassList_GET': ['table_change', 'GET', [], {}, CJ.JM_ClassList],
     55     # ('crm_010305_only_change_ClassList_GET', '010305_只能修改班级表_GET'),
     56     'crm_010306_only_change_ClassList_POST': ['table_change', 'POST', [], {}, CJ.JM_ClassList],
     57     # ('crm_010306_only_change_ClassList_POST', '010306_只能修改班级表_POST'),
     58     'crm_010307_only_delete_ClassList_GET': ['table_delete', 'GET', [], {}, CJ.JM_ClassList],
     59     # ('crm_010307_only_delete_ClassList_GET', '010307_只能删除班级表_GET'),
     60     'crm_010308_only_delete_ClassList_POST': ['table_delete', 'POST', [], {}, CJ.JM_ClassList],
     61     # ('crm_010308_only_delete_ClassList_POST', '010308_只能删除班级表_POST'),
     62 
     63     'crm_010401_only_view_Course_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Course],
     64     # ('crm_010401_only_view_Course_GET', '010401_只能查看课程表_GET'),
     65     'crm_010402_only_view_Course_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Course],
     66     # ('crm_010402_only_view_Course_POST', '010402_只能查看课程表_POST'),
     67     'crm_010403_only_add_Course_GET': ['table_add', 'GET', [], {}, CJ.JM_Course],
     68     # ('crm_010403_only_add_Course_GET', '010403_只能添加课程表_GET'),
     69     'crm_010404_only_add_Course_POST': ['table_add', 'POST', [], {}, CJ.JM_Course],
     70     # ('crm_010404_only_add_Course_POST', '010404_只能添加课程表_POST'),
     71     'crm_010405_only_change_Course_GET': ['table_change', 'GET', [], {}, CJ.JM_Course],
     72     # ('crm_010405_only_change_Course_GET', '010405_只能修改课程表_GET'),
     73     'crm_010406_only_change_Course_POST': ['table_change', 'POST', [], {}, CJ.JM_Course],
     74     # ('crm_010406_only_change_Course_POST', '010406_只能修改课程表_POST'),
     75     'crm_010407_only_delete_Course_GET': ['table_delete', 'GET', [], {}, CJ.JM_Course],
     76     # ('crm_010407_only_delete_Course_GET', '010407_只能删除课程表_GET'),
     77     'crm_010408_only_delete_Course_POST': ['table_delete', 'POST', [], {}, CJ.JM_Course],
     78     # ('crm_010408_only_delete_Course_POST', '010408_只能删除课程表_POST'),
     79 
     80     'crm_010501_only_view_Customer_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Customer],
     81     # ('crm_010501_only_view_Customer_GET', '010501_只能查看客户表_GET'),
     82     'crm_010502_only_view_Customer_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Customer],
     83     #  ('crm_010502_only_view_Customer_POST', '010502_只能查看客户表_POST'),
     84     'crm_010503_only_add_Customer_GET': ['table_add', 'GET', [], {}, CJ.JM_Customer],
     85     # ('crm_010503_only_add_Customer_GET', '010503_只能添加客户表_GET'),
     86     'crm_010504_only_add_Customer_POST': ['table_add', 'POST', [], {}, CJ.JM_Customer],
     87     # ('crm_010504_only_add_Customer_POST', '010504_只能添加客户表_POST'),
     88     'crm_010505_only_change_Customer_GET': ['table_change', 'GET', [], {}, CJ.JM_Customer],
     89     # ('crm_010505_only_change_Customer_GET', '010505_只能修改客户表_GET'),
     90     'crm_010506_only_change_Customer_POST': ['table_change', 'POST', [], {}, CJ.JM_Customer],
     91     # ('crm_010506_only_change_Customer_POST', '010506_只能修改客户表_POST'),
     92     'crm_010507_only_delete_Customer_GET': ['table_delete', 'GET', [], {}, CJ.JM_Customer],
     93     # ('crm_010507_only_delete_Customer_GET', '010507_只能删除客户表_GET'),
     94     'crm_010508_only_delete_Customer_POST': ['table_delete', 'POST', [], {}, CJ.JM_Customer],
     95     # ('crm_010508_only_delete_Customer_POST', '010508_只能删除客户表_POST'),
     96 
     97     'crm_010601_only_view_CustomerFollowUp_GET': ['table_data_list', 'GET', [], {}, CJ.JM_CustomerFollowUp],
     98     # ('crm_010601_only_view_CustomerFollowUp_GET', '010601_只能查看跟进表_GET'),
     99     'crm_010602_only_view_CustomerFollowUp_POST': ['table_data_list', 'POST', [], {}, CJ.JM_CustomerFollowUp],
    100     # ('crm_010602_only_view_CustomerFollowUp_POST', '010602_只能查看跟进表_POST'),
    101     'crm_010603_only_add_CustomerFollowUp_GET': ['table_add', 'GET', [], {}, CJ.JM_CustomerFollowUp],
    102     # ('crm_010603_only_add_CustomerFollowUp_GET', '010603_只能添加跟进表_GET'),
    103     'crm_010604_only_add_CustomerFollowUp_POST': ['table_add', 'POST', [], {}, CJ.JM_CustomerFollowUp],
    104     # ('crm_010604_only_add_CustomerFollowUp_POST', '010604_只能添加跟进表_POST'),
    105     'crm_010605_only_change_CustomerFollowUp_GET': ['table_change', 'GET', [], {}, CJ.JM_CustomerFollowUp],
    106     # ('crm_010605_only_change_CustomerFollowUp_GET', '010605_只能修改跟进表_GET'),
    107     'crm_010606_only_change_CustomerFollowUp_POST': ['table_change', 'POST', [], {}, CJ.JM_CustomerFollowUp],
    108     # ('crm_010606_only_change_CustomerFollowUp_POST', '010606_只能修改跟进表_POST'),
    109     'crm_010607_only_delete_CustomerFollowUp_GET': ['table_delete', 'GET', [], {}, CJ.JM_CustomerFollowUp],
    110     # ('crm_010607_only_delete_CustomerFollowUp_GET', '010607_只能删除跟进表_GET'),
    111     'crm_010608_only_delete_CustomerFollowUp_POST': ['table_delete', 'POST', [], {}, CJ.JM_CustomerFollowUp],
    112     # ('crm_010608_only_delete_CustomerFollowUp_POST', '010608_只能删除跟进表_POST'),
    113 
    114     'crm_010701_only_view_Enrollment_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Enrollment],
    115     # ('crm_010701_only_view_Enrollment_GET', '010701_只能查看报名表_GET'),
    116     'crm_010702_only_view_Enrollment_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Enrollment],
    117     # ('crm_010702_only_view_Enrollment_POST', '010702_只能查看报名表_POST'),
    118     'crm_010703_only_add_Enrollment_GET': ['table_add', 'GET', [], {}, CJ.JM_Enrollment],
    119     # ('crm_010703_only_add_Enrollment_GET', '010703_只能添加报名表_GET'),
    120     'crm_010704_only_add_Enrollment_POST': ['table_add', 'POST', [], {}, CJ.JM_Enrollment],
    121     # ('crm_010704_only_add_Enrollment_POST', '010704_只能添加报名表_POST'),
    122     'crm_010705_only_change_Enrollment_GET': ['table_change', 'GET', [], {}, CJ.JM_Enrollment],
    123     # ('crm_010705_only_change_Enrollment_GET', '010705_只能修改报名表_GET'),
    124     'crm_010706_only_change_Enrollment_POST': ['table_change', 'POST', [], {}, CJ.JM_Enrollment],
    125     # ('crm_010706_only_change_Enrollment_POST', '010706_只能修改报名表_POST'),
    126     'crm_010707_only_delete_Enrollment_GET': ['table_delete', 'GET', [], {}, CJ.JM_Enrollment],
    127     # ('crm_010707_only_delete_Enrollment_GET', '010707_只能删除报名表_GET'),
    128     'crm_010708_only_delete_Enrollment_POST': ['table_delete', 'POST', [], {}, CJ.JM_Enrollment],
    129     # ('crm_010708_only_delete_Enrollment_POST', '010708_只能删除报名表_POST'),
    130 
    131     'crm_010801_only_view_Payment_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Payment],
    132     # ('crm_010801_only_view_Payment_GET', '010801_只能查看缴费表_GET'),
    133     'crm_010802_only_view_Payment_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Payment],
    134     # ('crm_010802_only_view_Payment_POST', '010802_只能查看缴费表_POST'),
    135     'crm_010803_only_add_Payment_GET': ['table_add', 'GET', [], {}, CJ.JM_Payment],
    136     # ('crm_010803_only_add_Payment_GET', '010803_只能添加缴费表_GET'),
    137     'crm_010804_only_add_Payment_POST': ['table_add', 'POST', [], {}, CJ.JM_Payment],
    138     # ('crm_010804_only_add_Payment_POST', '010804_只能添加缴费表_POST'),
    139     'crm_010805_only_change_Payment_GET': ['table_change', 'GET', [], {}, CJ.JM_Payment],
    140     # ('crm_010805_only_change_Payment_GET', '010805_只能修改缴费表_GET'),
    141     'crm_010806_only_change_Payment_POST': ['table_change', 'POST', [], {}, CJ.JM_Payment],
    142     # ('crm_010806_only_change_Payment_POST', '010806_只能修改缴费表_POST'),
    143     'crm_010807_only_delete_Payment_GET': ['table_delete', 'GET', [], {}, CJ.JM_Payment],
    144     # ('crm_010807_only_delete_Payment_GET', '010807_只能删除缴费表_GET'),
    145     'crm_010808_only_delete_Payment_POST': ['table_delete', 'POST', [], {}, CJ.JM_Payment],
    146     # ('crm_010808_only_delete_Payment_POST', '010808_只能删除缴费表_POST'),
    147 
    148     'crm_010901_only_view_CourseRecord_GET': ['table_data_list', 'GET', [], {}, CJ.JM_CourseRecord],
    149     # ('crm_010901_only_view_CourseRecord_GET', '010901_只能查看上课表_GET'),
    150     'crm_010902_only_view_CourseRecord_POST': ['table_data_list', 'POST', [], {}, CJ.JM_CourseRecord],
    151     # ('crm_010902_only_view_CourseRecord_POST', '010902_只能查看上课表_POST'),
    152     'crm_010903_only_add_CourseRecord_GET': ['table_add', 'GET', [], {}, CJ.JM_CourseRecord],
    153     # ('crm_010903_only_add_CourseRecord_GET', '010903_只能添加上课表_GET'),
    154     'crm_010904_only_add_CourseRecord_POST': ['table_add', 'POST', [], {}, CJ.JM_CourseRecord],
    155     # ('crm_010904_only_add_CourseRecord_POST', '010904_只能添加上课表_POST'),
    156     'crm_010905_only_change_CourseRecord_GET': ['table_change', 'GET', [], {}, CJ.JM_CourseRecord],
    157     # ('crm_010905_only_change_CourseRecord_GET', '010905_只能修改上课表_GET'),
    158     'crm_010906_only_change_CourseRecord_POST': ['table_change', 'POST', [], {}, CJ.JM_CourseRecord],
    159     # ('crm_010906_only_change_CourseRecord_POST', '010906_只能修改上课表_POST'),
    160     'crm_010907_only_delete_CourseRecord_GET': ['table_delete', 'GET', [], {}, CJ.JM_CourseRecord],
    161     # ('crm_010907_only_delete_CourseRecord_GET', '010907_只能删除上课表_GET'),
    162     'crm_010908_only_delete_CourseRecord_POST': ['table_delete', 'POST', [], {}, CJ.JM_CourseRecord],
    163     # ('crm_010908_only_delete_CourseRecord_POST', '010908_只能删除上课表_POST'),
    164 
    165     'crm_011001_only_view_StudyRecord_GET': ['table_data_list', 'GET', [], {}, CJ.JM_StudyRecord],
    166     # ('crm_011001_only_view_StudyRecord_GET', '011001_只能查看学习表_GET'),
    167     'crm_011002_only_view_StudyRecord_POST': ['table_data_list', 'POST', [], {}, CJ.JM_StudyRecord],
    168     # ('crm_011002_only_view_StudyRecord_POST', '011002_只能查看学习表_POST'),
    169     'crm_011003_only_add_StudyRecord_GET': ['table_add', 'GET', [], {}, CJ.JM_StudyRecord],
    170     # ('crm_011003_only_add_StudyRecord_GET', '011003_只能添加学习表_GET'),
    171     'crm_011004_only_add_StudyRecord_POST': ['table_add', 'POST', [], {}, CJ.JM_StudyRecord],
    172     # ('crm_011004_only_add_StudyRecord_POST', '011004_只能添加学习表_POST'),
    173     'crm_011005_only_change_StudyRecord_GET': ['table_change', 'GET', [], {}, CJ.JM_StudyRecord],
    174     # ('crm_011005_only_change_StudyRecord_GET', '011005_只能修改学习表_GET'),
    175     'crm_011006_only_change_StudyRecord_POST': ['table_change', 'POST', [], {}, CJ.JM_StudyRecord],
    176     # ('crm_011006_only_change_StudyRecord_POST', '011006_只能修改学习表_POST'),
    177     'crm_011007_only_delete_StudyRecord_GET': ['table_delete', 'GET', [], {}, CJ.JM_StudyRecord],
    178     # ('crm_011007_only_delete_StudyRecord_GET', '011007_只能删除学习表_GET'),
    179     'crm_011008_only_delete_StudyRecord_POST': ['table_delete', 'POST', [], {}, CJ.JM_StudyRecord],
    180     # ('crm_011008_only_delete_StudyRecord_POST', '011008_只能删除学习表_POST'),
    181 
    182     'crm_011101_only_view_UserProfile_GET': ['table_data_list', 'GET', [], {}, CJ.JM_UserProfile],
    183     # ('crm_011101_only_view_UserProfile_GET', '011101_只能查看账号表_GET'),
    184     'crm_011102_only_view_UserProfile_POST': ['table_data_list', 'POST', [], {}, CJ.JM_UserProfile],
    185     # ('crm_011102_only_view_UserProfile_POST', '011102_只能查看账号表_POST'),
    186     'crm_011103_only_add_UserProfile_GET': ['table_add', 'GET', [], {}, CJ.JM_UserProfile],
    187     # ('crm_011103_only_add_UserProfile_GET', '011103_只能添加账号表_GET'),
    188     'crm_011104_only_add_UserProfile_POST': ['table_add', 'POST', [], {}, CJ.JM_UserProfile],
    189     # ('crm_011104_only_add_UserProfile_POST', '011104_只能添加账号表_POST'),
    190     'crm_011105_only_change_UserProfile_GET': ['table_change', 'GET', [], {}, CJ.JM_UserProfile],
    191     # ('crm_011105_only_change_UserProfile_GET', '011105_只能修改账号表_GET'),
    192     'crm_011106_only_change_UserProfile_POST': ['table_change', 'POST', [], {}, CJ.JM_UserProfile],
    193     # ('crm_011106_only_change_UserProfile_POST', '011106_只能修改账号表_POST'),
    194     'crm_011107_only_delete_UserProfile_GET': ['table_delete', 'GET', [], {}, CJ.JM_UserProfile],
    195     # ('crm_011107_only_delete_UserProfile_GET', '011107_只能删除账号表_GET'),
    196     'crm_011108_only_delete_UserProfile_POST': ['table_delete', 'POST', [], {}, CJ.JM_UserProfile],
    197     # ('crm_011108_only_delete_UserProfile_POST', '011108_只能删除账号表_POST'),
    198 
    199     'crm_011201_only_view_Role_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Role],
    200     # ('crm_011201_only_view_Role_GET', '011201_只能查看角色表_GET'),
    201     'crm_011202_only_view_Role_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Role],
    202     # ('crm_011202_only_view_Role_POST', '011202_只能查看角色表_POST'),
    203     'crm_011203_only_add_Role_GET': ['table_add', 'GET', [], {}, CJ.JM_Role],
    204     # ('crm_011203_only_add_Role_GET', '011203_只能添加角色表_GET'),
    205     'crm_011204_only_add_Role_POST': ['table_add', 'POST', [], {}, CJ.JM_Role],
    206     # ('crm_011204_only_add_Role_POST', '011204_只能添加角色表_POST'),
    207     'crm_011205_only_change_Role_GET': ['table_change', 'GET', [], {}, CJ.JM_Role],
    208     # ('crm_011205_only_change_Role_GET', '011205_只能修改角色表_GET'),
    209     'crm_011206_only_change_Role_POST': ['table_change', 'POST', [], {}, CJ.JM_Role],
    210     # ('crm_011206_only_change_Role_POST', '011206_只能修改角色表_POST'),
    211     'crm_011207_only_delete_Role_GET': ['table_delete', 'GET', [], {}, CJ.JM_Role],
    212     # ('crm_011207_only_delete_Role_GET', '011207_只能删除角色表_GET'),
    213     'crm_011208_only_delete_Role_POST': ['table_delete', 'POST', [], {}, CJ.JM_Role],
    214     # ('crm_011208_only_delete_Role_POST', '011208_只能删除角色表_POST'),
    215 
    216     'crm_011301_only_view_Tag_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Tag],
    217     # ('crm_011301_only_view_Tag_GET', '011301_只能查看标签表_GET'),
    218     'crm_011302_only_view_Tag_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Tag],
    219     # ('crm_011302_only_view_Tag_POST', '011302_只能查看标签表_POST'),
    220     'crm_011303_only_add_Tag_GET': ['table_add', 'GET', [], {}, CJ.JM_Tag],
    221     # ('crm_011303_only_add_Tag_GET', '011303_只能添加标签表_GET'),
    222     'crm_011304_only_add_Tag_POST': ['table_add', 'POST', [], {}, CJ.JM_Tag],
    223     # ('crm_011304_only_add_Tag_POST', '011304_只能添加标签表_POST'),
    224     'crm_011305_only_change_Tag_GET': ['table_change', 'GET', [], {}, CJ.JM_Tag],
    225     # (('crm_011305_only_change_Tag_GET', '011305_只能修改标签表_GET')
    226     'crm_011306_only_change_Tag_POST': ['table_change', 'POST', [], {}, CJ.JM_Tag],
    227     # ('crm_011306_only_change_Tag_POST', '011306_只能修改标签表_POST'),
    228     'crm_011307_only_delete_Tag_GET': ['table_delete', 'GET', [], {}, CJ.JM_Tag],
    229     # ('crm_011307_only_delete_Tag_GET', '011307_只能删除标签表_GET'),
    230     'crm_011308_only_delete_Tag_POST': ['table_delete', 'POST', [], {}, CJ.JM_Tag],
    231     # ('crm_011308_only_delete_Tag_POST', '011308_只能删除标签表_POST'),
    232 
    233     'crm_011401_only_view_FirstLayerMenu_GET': ['table_data_list', 'GET', [], {}, CJ.JM_FirstLayerMenu],
    234     # ('crm_011401_only_view_FirstLayerMenu_GET', '011401_只能查看一层菜单_GET'),
    235     'crm_011402_only_view_FirstLayerMenu_POST': ['table_data_list', 'POST', [], {}, CJ.JM_FirstLayerMenu],
    236     # ('crm_011402_only_view_FirstLayerMenu_POST', '011402_只能查看一层菜单_POST'),
    237     'crm_011403_only_add_FirstLayerMenu_GET': ['table_add', 'GET', [], {}, CJ.JM_FirstLayerMenu],
    238     # ('crm_011403_only_add_FirstLayerMenu_GET', '011403_只能添加一层菜单_GET'),
    239     'crm_011404_only_add_FirstLayerMenu_POST': ['table_add', 'POST', [], {}, CJ.JM_FirstLayerMenu],
    240     # ('crm_011404_only_add_FirstLayerMenu_POST', '011404_只能添加一层菜单_POST'),
    241     'crm_011405_only_change_FirstLayerMenu_GET': ['table_change', 'GET', [], {}, CJ.JM_FirstLayerMenu],
    242     # ('crm_011405_only_change_FirstLayerMenu_GET', '011405_只能修改一层菜单_GET'),
    243     'crm_011406_only_change_FirstLayerMenu_POST': ['table_change', 'POST', [], {}, CJ.JM_FirstLayerMenu],
    244     # ('crm_011406_only_change_FirstLayerMenu_POST', '011406_只能修改一层菜单_POST'),
    245     'crm_011407_only_delete_FirstLayerMenu_GET': ['table_delete', 'GET', [], {}, CJ.JM_FirstLayerMenu],
    246     # ('crm_011407_only_delete_FirstLayerMenu_GET', '011407_只能删除一层菜单_GET'),
    247     'crm_011408_only_delete_FirstLayerMenu_POST': ['table_delete', 'POST', [], {}, CJ.JM_FirstLayerMenu],
    248     # ('crm_011408_only_delete_FirstLayerMenu_POST', '011408_只能删除一层菜单_POST'),
    249 
    250     'crm_011501_only_view_SubMenu_GET': ['table_data_list', 'GET', [], {}, CJ.JM_SubMenu],
    251     # ('crm_011501_only_view_SubMenu_GET', '011501_只能查看二层菜单_GET'),
    252     'crm_011502_only_view_SubMenu_POST': ['table_data_list', 'POST', [], {}, CJ.JM_SubMenu],
    253     # ('crm_011502_only_view_SubMenu_POST', '011502_只能查看二层菜单_POST'),
    254     'crm_011503_only_add_SubMenu_GET': ['table_add', 'GET', [], {}, CJ.JM_SubMenu],
    255     # ('crm_011503_only_add_SubMenu_GET', '011503_只能添加二层菜单_GET'),
    256     'crm_011504_only_add_SubMenu_POST': ['table_add', 'POST', [], {}, CJ.JM_SubMenu],
    257     # ('crm_011504_only_add_SubMenu_POST', '011504_只能添加二层菜单_POST'),
    258     'crm_011505_only_change_SubMenu_GET': ['table_change', 'GET', [], {}, CJ.JM_SubMenu],
    259     # ('crm_011505_only_change_SubMenu_GET', '011505_只能修改二层菜单_GET'),
    260     'crm_011506_only_change_SubMenu_POST': ['table_change', 'POST', [], {}, CJ.JM_SubMenu],
    261     # ('crm_011506_only_change_SubMenu_POST', '011506_只能修改二层菜单_POST'),
    262     'crm_011507_only_delete_SubMenu_GET': ['table_delete', 'GET', [], {}, CJ.JM_SubMenu],
    263     # ('crm_011507_only_delete_SubMenu_GET', '011507_只能删除二层菜单_GET'),
    264     'crm_011508_only_delete_SubMenu_POST': ['table_delete', 'POST', [], {}, CJ.JM_SubMenu],
    265     # ('crm_011508_only_delete_SubMenu_POST', '011508_只能删除二层菜单_POST'),
    266 
    267     'crm_011601_only_view_Groups_GET': ['table_data_list', 'GET', [], {}, CJ.JM_Groups],
    268     # ('crm_011601_only_view_Groups_GET', '011601_只能查看权限组_GET'),
    269     'crm_011602_only_view_Groups_POST': ['table_data_list', 'POST', [], {}, CJ.JM_Groups],
    270     # ('crm_011602_only_view_Groups_POST', '011602_只能查看权限组_POST'),
    271     'crm_011603_only_add_Groups_GET': ['table_add', 'GET', [], {}, CJ.JM_Groups],
    272     # ('crm_011603_only_add_Groups_GET', '011603_只能添加权限组_GET'),
    273     'crm_011604_only_add_Groups_POST': ['table_add', 'POST', [], {}, CJ.JM_Groups],
    274     # ('crm_011604_only_add_Groups_POST', '011604_只能添加权限组_POST'),
    275     'crm_011605_only_change_Groups_GET': ['table_change', 'GET', [], {}, CJ.JM_Groups],
    276     #  ('crm_011605_only_change_Groups_GET', '011605_只能修改权限组_GET'),
    277     'crm_011606_only_change_Groups_POST': ['table_change', 'POST', [], {}, CJ.JM_Groups],
    278     # ('crm_011606_only_change_Groups_POST', '011606_只能修改权限组_POST'),
    279     'crm_011607_only_delete_Groups_GET': ['table_delete', 'GET', [], {}, CJ.JM_Groups],
    280     # ('crm_011607_only_delete_Groups_GET', '011607_只能删除权限组_GET'),
    281     'crm_011608_only_delete_Groups_POST': ['table_delete', 'POST', [], {}, CJ.JM_Groups],
    282     # ('crm_011608_only_delete_Groups_POST', '011608_只能删除权限组_POST'),
    283 
    284     'crm_011701_own_password_reset_GET': ['password_reset', 'GET', [], {}, CJ.own_password_reset],
    285     # ('crm_011701_own_password_reset_GET', '011701_自己密码重置_GET'),
    286     'crm_011702_own_password_reset_POST': ['password_reset', 'POST', [], {}, CJ.own_password_reset],
    287     # ('crm_011702_own_password_reset_POST', '011702_自己密码重置_POST'),
    288 
    289     'crm_020101_all_not_audit_GET': ['not_audit', 'GET', [], {}, ],
    290     # ('crm_020101_all_not_audit_GET', '020101_销售查看全部的客户未审核_GET'),
    291     'crm_020103_all_enrollment_GET': ['enrollment', 'GET', [], {}, ],
    292     # ('crm_020103_all_enrollment_GET', '020103_销售给全部的客户报名课程_GET'),
    293     'crm_020104_all_enrollment_POST': ['enrollment', 'POST', [], {}, ],
    294     # ('crm_020104_all_enrollment_POST', '020104_销售给全部的客户报名课程_POST'),
    295     'crm_020105_all_contract_review_GET': ['contract_review', 'GET', [], {}, ],
    296     # ('crm_020105_all_contract_review_GET', '020105_销售给全部的客户审核合同_GET'),
    297     'crm_020116_all_contract_review_POST': ['contract_review', 'POST', [], {}, ],
    298     # ('crm_020116_all_contract_review_POST', '020116_销售给全部的客户审核合同_POST'),
    299 
    300     'crm_020201_own_enrollment_GET': ['enrollment', 'GET', [], {}, CJ.own_enrollment],
    301     # ('crm_020201_own_enrollment_GET', '020201_销售给自己的客户报名课程_GET'),
    302     'crm_020202_own_enrollment_POST': ['enrollment', 'POST', [], {}, CJ.own_enrollment],
    303     # ('crm_020202_own_enrollment_POST', '020202_销售给自己的客户报名课程_POST'),
    304     'crm_020203_own_contract_review_GET': ['contract_review', 'GET', [], {}, CJ.own_contract_review],
    305     # ('crm_020203_own_contract_review_GET', '020203_销售给自己的客户审核合同_GET'),
    306     'crm_020204_own_contract_review_POST': ['contract_review', 'POST', [], {}, CJ.own_contract_review],
    307     # ('crm_020204_own_contract_review_POST', '020204_销售给自己的客户审核合同_POST'),
    308 
    309     'crm_030101_all_not_payment_GET': ['not_payment', 'GET', [], {}, ],
    310     # ('crm_030101_all_not_payment_GET', '030101_财务查看全部的客户未缴费_GET'),
    311     'crm_030102_all_not_payment_POST': ['not_payment', 'GET', [], {}, ],
    312     # ('crm_030102_all_not_payment_POST', '030102_财务查看全部的客户未缴费_POST'),
    313     'crm_030103_all_already_payment_GET': ['already_payment', 'GET', [], {}, ],
    314     # ('crm_030103_all_already_payment_GET', '030103_财务查看全部的客户已缴费_GET'),
    315     'crm_030104_all_already_payment_POST': ['already_payment', 'GET', [], {}, ],
    316     # ('crm_030104_all_already_payment_POST', '030104_财务查看全部的客户已缴费_POST'),
    317     'crm_030105_all_payment_GET': ['payment', 'GET', [], {}, ],
    318     # ('crm_030105_all_payment_GET', '030105_财务进行全部的客户缴费_GET'),
    319     'crm_030106_all_payment_POST': ['payment', 'POST', [], {}, ],
    320     # ('crm_030106_all_payment_POST', '030106_财务进行全部的客户缴费_POST'),
    321 
    322     'crm_040101_own_student_course_GET': ['student_course', 'GET', [], {}, ],
    323     # ('crm_040101_own_student_course_GET', '040101_学生查看自己的课程_GET'),
    324     'crm_040102_own_student_course_POST': ['student_course', 'POST', [], {}, ],
    325     # ('crm_040102_own_student_course_POST', '040102_学生查看自己的课程_POST'),
    326     'crm_040103_own_studyrecords_GET': ['studyrecords', 'GET', [], {}, CJ.own_studyrecords],
    327     # ('crm_040103_own_studyrecords_GET', '040103_学生自己的上课记录_GET'),
    328     'crm_040104_own_studyrecords_POST': ['studyrecords', 'POST', [], {}, CJ.own_studyrecords],
    329     # ('crm_050104_own_studyrecords_POST', '040104_学生自己的上课记录_POST'),
    330     'crm_040105_own_homework_detail_GET': ['homework_detail', 'GET', [], {}, CJ.own_homework_detail],
    331     # ('crm_040105_own_homework_detail_GET', '040105_学生自己的作业详情_GET'),
    332     'crm_040106_own_homework_detail_POST': ['homework_detail', 'POST', [], {}, CJ.own_homework_detail],
    333     # ('crm_040106_own_homework_detail_POST', '040106_学生自己的作业详情_POST'),
    334 
    335     'crm_050101_own_teacher_class_GET': ['teacher_class', 'GET', [], {}, ],
    336     # ('crm_050101_own_teacher_class_GET', '050101_讲师查看自己的班级_GET'),
    337     'crm_05102_own_teacher_class_POST': ['teacher_class', 'POST', [], {}, ],
    338     # ('crm_050102_own_teacher_class_POST', '050102_讲师查看自己的班级_POST'),
    339     'crm_050103_own_teacher_class_detail_GET': ['teacher_class_detail', 'GET', [], {}, CJ.own_teacher_class_detail],
    340     # ('crm_050103_own_teacher_class_detail_GET', '050103_讲师查看自己的课节详情_GET'),
    341     'crm_050104_own_teacher_class_detail_POST': ['teacher_class_detail', 'POST', [], {}, CJ.own_teacher_class_detail],
    342     # ('crm_050104_own_teacher_class_detail_POST', '050104_讲师查看自己的课节详情_POST'),
    343     'crm_050105_own_teacher_lesson_detail_GET': ['teacher_lesson_detail', 'GET', [], {}, CJ.own_teacher_lesson_detail],
    344     # ('crm_050105_own_teacher_lesson_detail_GET', '050105_讲师查看自己的课节学员_GET'),
    345     'crm_050106_own_teacher_lesson_detail_POST': ['teacher_lesson_detail', 'POST', [], {}, CJ.own_teacher_lesson_detail],
    346     # ('crm_050106_own_teacher_lesson_detail_POST', '050106_讲师查看自己的课节学员_POST'),
    347     'crm_050107_own_howk_down_GET': ['howk_down', 'GET', [], {}, CJ.own_howk_down],
    348     # ('crm_050107_own_howk_down_GET', '050107_讲师自己的学员作业下载_GET'),
    349     'crm_050108_own_howk_down_POST': ['howk_down', 'POST', [], {}, CJ.own_howk_down],
    350     # ('crm_050108_own_howk_down_POST', '050108_讲师自己的学员作业下载_POST'),
    351 
    352     'crm_060101_own_coursetop_details_GET': ['coursetop_details', 'GET', [], {}, CJ.JM_crm_classlist_teachers],
    353     # ('crm_060101_own_coursetop_details_GET', '060101_讲师查看自己的班级排名详情_GET'),
    354     'crm_060102_own_coursetop_details_POST': ['coursetop_details', 'POST', [], {}, CJ.JM_crm_classlist_teachers],
    355     # ('crm_060102_own_coursetop_details_POST', '060102_讲师查看自己的班级排名详情_POST'),
    356     'crm_060103_own_coursetop_score_GET': ['coursetop_score', 'GET', [], {}, CJ.JM_crm_classlist_teachers],
    357     # ('crm_060103_own_coursetop_score_GET', '060103_讲师查看自己的班级分数排行_GET'),
    358     'crm_060104_own_coursetop_score_POST': ['coursetop_score', 'POST', [], {}, CJ.JM_crm_classlist_teachers],
    359     # ('crm_060104_own_coursetop_score_POST', '060104_讲师查看自己的班级排分数排行_POST'),
    360     'crm_060105_own_coursetop_homework_GET': ['coursetop_homework', 'GET', [], {}, CJ.JM_crm_classlist_teachers],
    361     # ('crm_060105_own_coursetop_homework_GET', '060105_讲师查看自己的班级作业排行_GET'),
    362     'crm_060106_own_coursetop_homework_POST': ['coursetop_homework', 'POST', [], {}, CJ.JM_crm_classlist_teachers],
    363     # ('crm_060106_own_coursetop_homework_POST', '060106_讲师查看自己的班级作业排行_POST'),
    364     'crm_060107_own_coursetop_attendance_GET': ['coursetop_attendance', 'GET', [], {}, CJ.JM_crm_classlist_teachers],
    365     # ('crm_060107_own_coursetop_attendance_GET', '060107_讲师查看自己的班级出勤排行_GET'),
    366     'crm_060108_own_coursetop_attendance_POST': ['coursetop_attendance', 'POST', [], {}, CJ.JM_crm_classlist_teachers],
    367     # ('crm_060108_own_coursetop_attendance_POST', '060108_讲师查看自己的班级出勤排行_POST'),
    368 
    369 
    370 }
    371 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
    # permission_list.py

      1 # CJ.py
      2 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
      3 import re #正则
      4 from crm import models #数据库
      5 
      6 # ————————01大类权限————————
      7 #010201_只能查看校区表_GET
      8 def JM_Branch(request,*args,**kwargs):
      9     url_path = request.path  # 获取URL
     10     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
     11     url_model_name=url_list[2]
     12     model_name = 'branch'
     13     if url_model_name == model_name: #防止其他表通过权限
     14         return True
     15     else:
     16         return False
     17 
     18 # 010301_只能查看班级表_GET
     19 def JM_ClassList(request, *args, **kwargs):
     20     url_path = request.path  # 获取URL
     21     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
     22     url_model_name = url_list[2]
     23     model_name = 'classlist'
     24     if url_model_name == model_name:  # 防止其他表通过权限
     25         return True
     26     else:
     27         return False
     28 
     29 # 010401_只能查看课程表_GET
     30 def JM_Course(request, *args, **kwargs):
     31     url_path = request.path  # 获取URL
     32     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
     33     url_model_name = url_list[2]
     34     model_name = 'course'
     35     if url_model_name == model_name:  # 防止其他表通过权限
     36         return True
     37     else:
     38         return False
     39 
     40 # 010501_只能查看客户表_GET
     41 def JM_Customer(request, *args, **kwargs):
     42     url_path = request.path  # 获取URL
     43     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
     44     url_model_name = url_list[2]
     45     model_name = 'customer'
     46     if url_model_name == model_name:  # 防止其他表通过权限
     47         return True
     48     else:
     49         return False
     50 
     51 
     52 #010601_只能查看跟进表_GET
     53 def JM_CustomerFollowUp(request,*args,**kwargs):
     54     url_path = request.path  # 获取URL
     55     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
     56     url_model_name=url_list[2]
     57     model_name = 'customerfollowup'
     58     if url_model_name == model_name: #防止其他表通过权限
     59         return True
     60     else:
     61         return False
     62 
     63 # 010701_只能查看报名表_GET
     64 def JM_Enrollment(request, *args, **kwargs):
     65     url_path = request.path  # 获取URL
     66     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
     67     url_model_name = url_list[2]
     68     model_name = 'enrollment'
     69     if url_model_name == model_name:  #防止其他表通过权限
     70         return True
     71     else:
     72         return False
     73 
     74 # 010801_只能查看缴费表_GET
     75 def JM_Payment(request, *args, **kwargs):
     76     url_path = request.path  # 获取URL
     77     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
     78     url_model_name = url_list[2]
     79     model_name = 'payment'
     80     if url_model_name == model_name:  #防止其他表通过权限
     81         return True
     82     else:
     83         return False
     84 
     85 
     86 #010901_只能查看上课表_GET
     87 def JM_CourseRecord(request,*args,**kwargs):
     88     url_path = request.path  # 获取URL
     89     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
     90     url_model_name=url_list[2]
     91     model_name = 'courserecord'
     92     if url_model_name == model_name: #防止其他表通过权限
     93         return True
     94     else:
     95         return False
     96 
     97 
     98 # 011001_只能查看学习表_GET
     99 def JM_StudyRecord(request, *args, **kwargs):
    100     url_path = request.path  # 获取URL
    101     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    102     url_model_name = url_list[2]
    103     model_name = 'studyrecord'
    104     if url_model_name == model_name:  #防止其他表通过权限
    105         return True
    106     else:
    107         return False
    108 
    109 
    110 # 011101_只能查看账号表_GET
    111 def JM_UserProfile(request, *args, **kwargs):
    112     url_path = request.path  # 获取URL
    113     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    114     url_model_name = url_list[2]
    115     model_name = 'userprofile'
    116     if url_model_name == model_name:  #防止其他表通过权限
    117         return True
    118     else:
    119         return False
    120 
    121 
    122 #011201_只能查看角色表_GET
    123 def JM_Role(request,*args,**kwargs):
    124     url_path = request.path  # 获取URL
    125     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
    126     url_model_name=url_list[2]
    127     model_name = 'role'
    128     if url_model_name == model_name: #防止其他表通过权限
    129         return True
    130     else:
    131         return False
    132 
    133 
    134 
    135 #010301_只能查看班级表_GET
    136 def JM_Tag(request,*args,**kwargs):
    137     url_path = request.path  # 获取URL
    138     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
    139     url_model_name=url_list[2]
    140     model_name = 'tag'
    141     if url_model_name == model_name: #防止其他表通过权限
    142         return True
    143     else:
    144         return False
    145 
    146 
    147 #011401_只能查看一层菜单_GET
    148 def JM_FirstLayerMenu(request,*args,**kwargs):
    149     url_path = request.path  # 获取URL
    150     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
    151     url_model_name=url_list[2]
    152     model_name = 'firstlayermenu'
    153     if url_model_name == model_name: #防止其他表通过权限
    154         return True
    155     else:
    156         return False
    157 
    158 
    159 # 011501_只能查看二层菜单_GET
    160 def JM_SubMenu(request, *args, **kwargs):
    161     url_path = request.path  # 获取URL
    162     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    163     url_model_name = url_list[2]
    164     model_name = 'submenu'
    165     if url_model_name == model_name:  #防止其他表通过权限
    166         return True
    167     else:
    168         return False
    169 
    170 
    171 #011601_只能查看权限组_GET
    172 def JM_Groups(request,*args,**kwargs):
    173     url_path = request.path  # 获取URL
    174     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
    175     url_model_name=url_list[2]
    176     model_name = 'groups'
    177     if url_model_name == model_name: #防止其他表通过权限
    178         return True
    179     else:
    180         return False
    181 
    182 #011701_自己密码重置_GET
    183 def own_password_reset(request,*args,**kwargs):
    184     url_path = request.path  # 获取URL 路径
    185     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    186     url_model_name = url_list[4]    #字符串
    187     url_parameter =int(url_list[3])  #字符串转数字
    188     model_name = 'password_reset'  #字符串
    189     if url_model_name == model_name:  #防止其他表通过权限
    190         if url_parameter == request.user.id:  # 参数 等于 #当前登陆的ID
    191             return True
    192         else:
    193             return False
    194     else:
    195         return False
    196  # ————————01大类权限————————
    197 
    198  # ————————02大类权限————————
    199 #020103_销售给自己的客户报名课程_GET
    200 #销售 #客户招生#报名流程一 下一步
    201 def own_enrollment(request,*args,**kwargs):
    202     url_path = request.path #获取URL 路径
    203     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
    204     url_model_name= url_list[3]
    205     url_parameter =int(url_list[2])
    206     model_name = 'enrollment'
    207     if url_model_name==model_name: #防止其他表通过权限
    208         if request.user.id: #如果有ID
    209             list= request.user.customer_set.all()#获取ID 的客户表
    210             list_id=[]
    211             for obtain in list:#循环客户表ID
    212                 results=obtain.id
    213                 list_id.append(results)#生成列表
    214         if url_parameter in list_id: #对比URL参数 在不在 客户表ID里
    215             return True
    216         else:
    217             return False
    218     else:
    219         return False
    220 
    221 
    222 #020107_销售给自己的客户审核合同_GET
    223 #销售 # 报名流程三  审核
    224 def own_contract_review(request,*args,**kwargs):
    225     url_path = request.path #获取URL 路径
    226     url_list=re.findall('(w+)',url_path) #正者表达式 获取参数
    227     url_model_name= url_list[1]  #字符串
    228     url_parameter =int(url_list[2]) #字符串转数字
    229     model_name='contract_review' #字符串
    230     if url_model_name==model_name: #防止其他表通过权限
    231         if request.user.id: #如果有ID
    232             list= request.user.enrollment_set.all()#获取ID 的客户表
    233             list_id=[]  #数字列表
    234             for obtain in list:#循环客户表ID
    235                 results=obtain.id
    236                 list_id.append(results)#生成列表
    237         if url_parameter in list_id: #对比URL参数 在不在 列表里
    238             return True
    239         else:
    240             return False
    241     else:
    242         return False
    243 
    244 # ————————02大类权限————————
    245 
    246 # ————————04大类权限————————
    247 # 040103_学生自己的上课记录_GET
    248 def own_studyrecords(request, *args, **kwargs):
    249     url_path = request.path  # 获取URL 路径 /bpm/studyrecords/6/
    250     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    251     url_model_name = url_list[1]
    252     url_parameter = int( url_list[2] )
    253     model_name = 'studyrecords'
    254     if url_model_name == model_name:  # 防止其他表通过权限
    255         if request.user.id:  # 如果有ID
    256             list = request.user.stu_account.enrollment_set.all()  # 根据ID关联学生的报名ID
    257             list_id = []
    258             for obtain in list:
    259                 results = obtain.id
    260                 list_id.append( results )  # 生成列表
    261         if url_parameter in list_id:  # 对比URL参数 在不在 ID列表里
    262             return True
    263         else:
    264             return False
    265     else:
    266         return False
    267 
    268 
    269 # 040105_学生自己的作业详情_GET
    270 def own_homework_detail(request, *args, **kwargs):
    271     url_path = request.path  # 获取URL 路径 /bpm/homework_detail/2/25/
    272     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    273     url_model_name = url_list[1]  #字符串
    274     url_parameter =(int(url_list[2]),)  #元组
    275     url_parameter2 = int(url_list[3]),  #元组
    276     model_name = 'homework_detail'#字符串
    277     if url_model_name == model_name: #防止其他表通过权限
    278         if request.user.id:  # 如果有ID
    279             list_id = request.user.stu_account.enrollment_set.values_list('id')  # 根据登陆ID关联学生的报名ID
    280         if url_parameter in list_id:  # 对比URL参数 在不在 ID列表里
    281             StudyRecord_id = models.StudyRecord.objects.filter(student_id=url_parameter).values_list('id')
    282             if url_parameter2 in StudyRecord_id: # 对比URL参数2 在不在 ID列表里
    283                 return True
    284             else:
    285                 return False
    286         else:
    287             return False
    288     else:
    289         return False
    290 
    291 # ————————04大类权限————————
    292 
    293 # ————————05大类权限————————
    294 # 050103_讲师查看自己的课节详情_GET
    295 def own_teacher_class_detail(request, *args, **kwargs):
    296     url_path = request.path  # 获取URL 路径 /bpm/teacher_class_detail/1/
    297     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    298     url_model_name = url_list[1]
    299     url_parameter = (int(url_list[2]),)  # <class 'tuple'> (1,)
    300     model_name = 'teacher_class_detail'
    301     if url_model_name == model_name: #防止其他表通过权限
    302         if request.user.id:  # 如果有ID
    303             list_id = request.user.classlist_set.values_list('id')  # 根据ID获取班级ID
    304         if url_parameter in list_id:  # 对比URL参数 在不在 ID列表里
    305             return True
    306         else:
    307             return False
    308     else:
    309         return False
    310 
    311 # 050105_讲师查看自己的课节学员_GET
    312 def own_teacher_lesson_detail(request, *args, **kwargs):
    313     url_path = request.path  # 获取URL 路径 /bpm/teacher_lesson_detail/2/2/
    314     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    315     url_model_name = url_list[1]        #字符串
    316     url_parameter = int(url_list[2]),    #元组
    317     url_parameter2 = (int(url_list[3]),) #元组
    318     model_name = 'teacher_lesson_detail'#字符串
    319     if url_model_name == model_name: #防止其他表通过权限
    320         if request.user.id:  # 如果有ID
    321             list_id= request.user.classlist_set.values_list( 'id' ) # 元组列表 #根据登陆ID 反查班级ID列表
    322         if url_parameter in list_id :  # 对比URL参数 在不在 ID列表里
    323             CourseRecord_id = models.CourseRecord.objects.filter( from_class_id=url_parameter ).values_list( 'id' )# 元组列表
    324             if url_parameter2 in CourseRecord_id: # 对比URL参数2 在不在 ID列表里
    325                 return True
    326             else:
    327                 return False
    328         else:
    329             return False
    330     else:
    331         return False
    332 
    333 # 050107_讲师自己的学员作业下载_GET
    334 def own_howk_down(request, *args, **kwargs):
    335     url_path = request.path  # 获取URL 路径 /bpm/homeworks/3/3/17/
    336     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    337     url_model_name = url_list[1] #字符串
    338     url_parameter = (int(url_list[2]),)  #元组# <class 'tuple'> (1,)
    339     url_parameter2 = (int(url_list[3]),) #元组
    340     model_name = 'homeworks' #字符串
    341     if url_model_name == model_name: #防止其他表通过权限
    342         if request.user.id:  # 如果有ID
    343             list_id = request.user.classlist_set.values_list( 'id' ) # 元组列表 #根据登陆ID 反查班级ID列表
    344         if url_parameter in list_id :  # 对比URL参数 在不在 ID列表里
    345             CourseRecord_id = models.CourseRecord.objects.filter( from_class_id=url_parameter ).values_list( 'id' )
    346             if url_parameter2 in CourseRecord_id: # 对比URL参数2 在不在 ID列表里
    347                 return True
    348             else:
    349                 return False
    350         else:
    351             return False
    352     else:
    353         return False
    354 
    355 # ————————05大类权限————————
    356 
    357 # ————————06大类权限————————
    358 
    359 # 060101_讲师查看自己的班级排名详情_GET
    360 def JM_crm_classlist_teachers(request, *args, **kwargs):
    361     url_path = request.path  # 获取URL 路径 /bpm/coursetop_details/3/
    362     url_list = re.findall( '(w+)', url_path )  # 正者表达式 获取参数
    363     url_model_name = (url_list[1],)#字符串元组
    364     url_parameter = (int(url_list[2]),)  # 元组 #<class 'tuple'> (1,)
    365     model_name =[('coursetop_details',),('coursetop_score',),('coursetop_homework',),('coursetop_attendance',),]
    366     if url_model_name in model_name: #防止其他表通过权限
    367         if request.user.id:  # 如果有ID
    368             list_id = request.user.classlist_set.values_list('id')  # 根据ID获取班级ID
    369             print('list_id::',list_id)
    370         if url_parameter in list_id:  # 对比URL参数 在不在 ID列表里
    371             return True
    372         else:
    373             return False
    374     else:
    375         return False
    376 
    377 # ————————06大类权限————————
    378 
    379 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
    # CJ.py

      1 # permission.py
      2 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
      3 from django.urls import resolve # resolve解析URL
      4 from django.shortcuts import render,redirect,HttpResponse #页面返回
      5 from permissions.permission_list import perm_dic #权限字典
      6 
      7 def perm_check(*args,**kwargs):
      8     print( '执行perm_check:', *args, **kwargs )
      9     request = args[0]#
     10     # print(request) #<WSGIRequest: GET '/king_admin/crm/firstlayermenu/4/change/'>
     11 
     12     resolve_url_obj = resolve(request.path)#反解URL路径#获取当前的URL# resolve解析URL#生成实例
     13     print('反解URL路径:',resolve_url_obj)#ResolverMatch(func=permissions.permission.inner, args=('crm', 'firstlayermenu', '4'), kwargs={}, url_name=table_change, app_names=[], namespaces=[])
     14     current_url_name = resolve_url_obj.url_name  # 当前url的url_name
     15     print('当前用户:',request.user,'当前url的url_name:',current_url_name)#admin2 当前url的url_name: table_change
     16 
     17     permission_list= request.user.user_permissions.values_list('codename') # 根据 登陆的ID 获取 拥有的权限列表
     18     print('拥有的权限列表',permission_list)
     19 
     20     permission_group = request.user.groups.all().values_list('permissions__codename')    # 根据 登陆的ID 获取 拥有的组
     21     print('拥有的权限组',permission_group)
     22 
     23     match_key = None
     24     match_results = [False,] #后面会覆盖,加个False是为了让all(match_results)不出错
     25 
     26     for permission_key,permission_val in  perm_dic.items():#从权限字典中取相关字段 #crm_table_index':['1','table_index','GET',[],{},],
     27         # print('循环权限表',((permission_key),))
     28         if ((permission_key),) in permission_list or ((permission_key),) in permission_group:#权限列表是元组
     29             per_url_name = permission_val[0] #URL
     30             per_method  = permission_val[1] #GET #POST #请求方法
     31             perm_args = permission_val[2]  # 列表参数
     32             perm_kwargs = permission_val[3]# 字典参数
     33             custom_perm_func = None if len(permission_val) == 4 else permission_val[4] #url判断 #自定义权限钩子
     34             # 'crm_can_access_my_clients':['table_list','GET',[],{'perm_check':33,'arg2':'test'}, custom_perm_logic.only_view_own_customers],
     35             # print('URL:',per_url_name,'请求方法:',per_method,'列表参数:',perm_args,'字典参数:',perm_kwargs,'自定义权限钩子:',custom_perm_func)
     36 
     37 
     38             if per_url_name == current_url_name: #权限字典的 URL  ==当前请求的url #crm_table_index':['URL','请求方法',[列表参数],{字典参数},],
     39                 if per_method == request.method: #权限字典的 请求方法 == 当前请求的方法  #crm_table_index':['URL','请求方法',[列表参数],{字典参数},],
     40                     #逐个匹配参数,看每个参数时候都能对应的上。
     41                     args_matched = False #参数匹配 #仅供参数
     42                     for item in perm_args: #循环列表参数 #crm_table_index':['URL','请求方法',[列表参数],{字典参数},],
     43                         request_method_func = getattr(request,per_method) #反射 #请求方法 #GET #POST
     44                         if request_method_func.get(item,None):# 如果request字典中有此参数
     45                             args_matched = True
     46                         else:
     47                             print("参数不匹配......")
     48                             args_matched = False
     49                             break  # 有一个参数不能匹配成功,则判定为假,退出该循环。
     50                     else:
     51                         args_matched = True #没有执行 break 表示 列表匹配成功 #防止列表没有使用参数时出错
     52 
     53                     #匹配有特定值的参数
     54                     kwargs_matched = False
     55                     for k,v in perm_kwargs.items(): #循环字典参数#crm_table_index':['URL','请求方法',[列表参数],{字典参数},],
     56                         request_method_func = getattr(request, per_method) #反射 #请求方法 #GET #POST
     57                         arg_val = request_method_func.get(k, None)  # request字典中有此参数
     58                         print("perm kwargs check:",arg_val,type(arg_val),v,type(v))
     59                         if arg_val == str(v): #匹配上了特定的参数 及对应的 参数值, 比如,需要request 对象里必须有一个叫 user_id=3的参数
     60                             kwargs_matched = True
     61                         else:
     62                             kwargs_matched = False
     63                             break # 有一个参数不能匹配成功,则判定为假,退出该循环。
     64                     else:
     65                         kwargs_matched = True
     66 
     67 
     68                     #自定义权限钩子
     69                     perm_func_matched = False
     70                     if custom_perm_func: #如果有定义
     71                         if custom_perm_func(request,args,kwargs):#def only_view_own_customers(request,*args,**kwargs):
     72                             perm_func_matched = True
     73                         else:
     74                             perm_func_matched = False #使整条权限失效
     75                             print('自定义权限钩子没有通过',perm_func_matched)
     76                     else: #没有定义权限钩子,所以默认通过
     77                         perm_func_matched = True
     78 
     79                     match_results = [args_matched,kwargs_matched,perm_func_matched] #列表
     80                     print("匹配结果: ", match_results) # [True, True, True]
     81                     if all(match_results): #都匹配上了 #都返回 True
     82                         match_key = permission_key # 给 match_key = None 赋值
     83                         break  #跳出大循环
     84 
     85     if all(match_results): #如果都匹配成功     #'crm_table_index':['table_index','GET',[],{},],
     86         app_name, *per_name = match_key.split('_') #先给app_name赋一个值,其他的值都给*per_name     'crm_table_index':
     87         print("权限名:",match_key,'权限:',match_results)#crm_010902_only_view_CourseRecord_POST [True, True, True]
     88         print('分割:',app_name, *per_name) #  crm 010902 only view CourseRecord POST
     89         perm_obj = '%s.%s' % (app_name,match_key)#'crm.table_index' #    url(r'^(w+)/$', views.table_index, name='table_index'),  # 单个具体app页面
     90         print("生成权限:",perm_obj) #crm.crm_010902_only_view_CourseRecord_POST
     91         if request.user.has_perm(perm_obj):
     92             print('当前用户有此权限')
     93             return True
     94         else:
     95             print('当前用户没有该权限')
     96             return False
     97     else:
     98         print("未匹配到权限项,当前用户无权限")
     99 
    100 def check_permission(func):
    101     print('权限func',func)#权限func <function table_data_list at 0x030636A8> #循环 URL name
    102     def inner(*args,**kwargs):
    103         print('开始权限匹配:',type(args))
    104         request = args[0]#请求第一个
    105         print('判断登陆情况:')
    106         if request.user.id == None:
    107             print('未登陆')
    108             return redirect( '/gbacc/gbacc_login/' )#返回登陆页面
    109         else:
    110             if request.user.is_superuser == True:
    111                 print('超级管理员')
    112                 return func( *args, **kwargs )  #直接返回 真
    113             print( '已登陆,判断有perm_check(*args,**kwargs)去执行' )
    114             if not perm_check(*args,**kwargs): #如果返回不为真 #没权限
    115                 print('#没权限',perm_check(*args,**kwargs))
    116                 request = args[0]
    117                 return HttpResponse('你没有这个权限')
    118             print('有权限',func(*args,**kwargs)) #<HttpResponse status_code=200, "text/html; charset=utf-8">
    119             return func(*args,**kwargs)
    120     print('inner',inner)
    121     return  inner #返回 真或假
    122 # ————————74PerfectCRM实现CRM权限和权限组限制URL————————
    # permission.py

      1 # views
      2 
      3 # ————————02PerfectCRM创建ADMIN页面————————
      4 from django.shortcuts import render
      5 
      6 # ————————04PerfectCRM实现King_admin注册功能————————
      7 # from django import conf #配置文件
      8 # print("dj conf:",conf) #配置文件
      9 # print("dj conf:",conf.settings)#配置文件.设置
     10 # ————————04PerfectCRM实现King_admin注册功能————————
     11 
     12 # ————————04PerfectCRM实现King_admin注册功能————————
     13 from king_admin import app_config  # 自动调用  动态加载类和函数
     14 # ————————04PerfectCRM实现King_admin注册功能————————
     15 
     16 # ————————04PerfectCRM实现King_admin注册功能————————
     17 # from king_admin.base_admin import registered_sites # registered_sites={}
     18 from king_admin import base_admin
     19 # ————————04PerfectCRM实现King_admin注册功能————————
     20 
     21 # ————————11PerfectCRM实现King_admin基本分页————————
     22 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger  # 分页功能
     23 # ————————11PerfectCRM实现King_admin基本分页————————
     24 
     25 # ————————46PerfectCRM实现登陆后页面才能访问————————
     26 from  django.contrib.auth.decorators import login_required
     27 # ————————46PerfectCRM实现登陆后页面才能访问————————
     28 
     29 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     30 from permissions.permission import check_permission #权限控制
     31 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     32 
     33 def app_index(request):
     34     # ————————04PerfectCRM实现King_admin注册功能————————
     35     # for app in conf.settings.INSTALLED_APPS:
     36     #     print(app)#循环打印 配置文件.设置.安装应用程序#.Perfectcustomersettings里的INSTALLED_APPS列表
     37     # ————————04PerfectCRM实现King_admin注册功能————————
     38 
     39     # ————————04PerfectCRM实现King_admin注册功能————————
     40     # return render(request, 'king_admin/app_index.html')
     41     # print("registered_sites",registered_sites)
     42     # return render(request, 'king_admin/app_index.html')
     43     # ————————04PerfectCRM实现King_admin注册功能————————
     44 
     45     # ————————04PerfectCRM实现King_admin注册功能————————
     46     # print("registered_sites", base_admin.registered_sites)
     47     # return render(request, 'king_admin/app_index.html')
     48     # ————————04PerfectCRM实现King_admin注册功能————————
     49 
     50     # ————————05PerfectCRM实现King_admin注册功能获取内存————————
     51     print("registered_sites", base_admin.site.registered_sites)
     52     return render(request, 'king_admin/app_index.html', {"site": base_admin.site})
     53 
     54 
     55 # ————————05PerfectCRM实现King_admin注册功能获取内存————————
     56 
     57 # ————————02PerfectCRM创建ADMIN页面————————
     58 
     59 # ————————13PerfectCRM实现King_admin分页页数————————
     60 # 处理def table_data_list(request,app_name,model_name):里的内容,
     61 def filter_querysets(request, queryset):
     62     condtions = {}  # 定义一个字典用来存过滤的条件
     63     for k, v in request.GET.items():  # 不需要空的,判断是否为空
     64         # ————————18PerfectCRM实现King_admin搜索关键字————————
     65         # ————————17PerfectCRM实现King_admin单列排序————————
     66         # if k=="page":continue##kingadmin分页功能
     67 
     68         # if k=="page":continue##kingadmin分页功能 #写法一
     69         # elif k=="_o":continue##kingadmin排序功能  <a href="?_o={{ column }}">{{ column }}</a>
     70 
     71         # if k in ("page","_o") :continue #kingadmin分页功能   #kingadmin排序功能   #写法二
     72 
     73         # if k == "page"or k == "_o": #保留的分页关键字 和  排序关键字 #写法三
     74         #     continue #continue是结束单次循环
     75         # ————————17PerfectCRM实现King_admin单列排序————————
     76         if k in ("page", "_o", "_q"): continue  # kingadmin分页,排序,搜索#判断标签是否存在 自定义的名称
     77         # ————————18PerfectCRM实现King_admin搜索关键字————————
     78 
     79 
     80         # ————————15PerfectCRM实现King_admin多条件过滤————————
     81         if v:
     82             condtions[k] = v  # 进行配对字典
     83             # ————————15PerfectCRM实现King_admin多条件过滤————————
     84     query_res = queryset.filter(**condtions)
     85 
     86     return query_res, condtions
     87 
     88 
     89 # ————————13PerfectCRM实现King_admin分页页数————————
     90 
     91 # ————————59PerfectCRM实现king_admin行内编辑————————
     92 from  king_admin import form
     93 
     94 
     95 def batch_update(request, editable_data, admin_obj):
     96     """table objects batch update , for list_editable feature"""
     97     errors = []  # 错误信息
     98     for row_data in editable_data:
     99         obj_id = row_data.get('id')  # 获取这行ID号
    100         try:
    101             if obj_id:
    102                 print("如果有ID编辑数据:", row_data, list(row_data.keys()))
    103                 obj = admin_obj.model.objects.get(id=obj_id)  # 获取编辑的ID
    104                 model_form = form.create_form(admin_obj.model, list(row_data.keys()),
    105                                               admin_obj, request=request, partial_update=True)  # 进行数据验证处理
    106                 form_obj = model_form(instance=obj, data=row_data)  # 编辑的ID #验证的内容
    107                 if form_obj.is_valid():  # 验证通过
    108                     form_obj.save()  # 保存新内容
    109                     print('保存。。。。')
    110 
    111                 else:
    112                     print("可编辑列表形式", row_data, form_obj.errors)
    113 
    114                     errors.append([form_obj.errors, obj])  # 添加错误信息
    115 
    116                     # for column in row_data:
    117                     #     if column != "id":#id no need change
    118                     #         #print("-----column",column,row_data[column],type(row_data[column]))
    119                     #         if row_data[column] in ('True','False'):
    120                     #             if obj._meta.get_field(column).get_internal_type() == "BooleanField":
    121                     #                 setattr(obj, column, eval(row_data[column]))
    122                     #                 #print("setting column [%s] to [%s]" %(column,row_data[column]), eval(row_data[column]))
    123                     #             else:
    124                     #                 setattr(obj, column, row_data[column])
    125                     #         else:
    126                     #             setattr(obj,column,row_data[column])
    127                     #
    128                     # obj.save()
    129 
    130         # except Exception as e:
    131         except KeyboardInterrupt as e:
    132             return False, [e, obj]
    133     if errors:
    134         return False, errors
    135     return True, []
    136 
    137 
    138 # ————————59PerfectCRM实现king_admin行内编辑————————
    139 
    140 # ————————08PerfectCRM实现King_admin显示注册表的字段表头————————
    141 @login_required  # 登陆后页面才能访问
    142 @check_permission #权限控制
    143 def table_data_list(request, app_name, model_name):
    144     # 通过2个参数到base_admin里获取class AdminRegisterException(Exception): 的对象
    145     admin_obj = base_admin.site.registered_sites[app_name][model_name]  # base_admin
    146 
    147     # ————————24PerfectCRM实现King_admin自定义操作数据————————
    148     if request.method == "POST":  # 批量操作
    149         action = request.POST.get("action_select")  # 要调用的自定制功能函数
    150         selected_ids = request.POST.get("selected_ids")  # 前端提交的数据
    151         print(selected_ids, type(selected_ids), "selected_ids-----")
    152         # if type(selected_ids)!='str':
    153         # selected_ids = json.loads(selected_ids)#进行转换数据
    154         print(selected_ids, type(action), action, "selected_ids==========")
    155         # print("action:",selected_ids,action)
    156         # ————————59PerfectCRM实现king_admin行内编辑————————
    157         import json
    158         editable_data = request.POST.get("editable_data")  # 获取前端可编辑的数据
    159         print('编辑数据:', editable_data)
    160         if editable_data:  # for list editable
    161             editable_data = json.loads(editable_data)  # 进行转换数据
    162             # print("editable",editable_data)
    163             res_state, errors = batch_update(request, editable_data, admin_obj)  # 进行部分更新操作
    164         else:
    165             # ————————59PerfectCRM实现king_admin行内编辑————————
    166             if selected_ids:
    167                 # selected_ids = json.loads(selected_ids)#进行转换数据
    168                 selected_objs = admin_obj.model.objects.filter(id__in=selected_ids.split(','))  # 返回之前所选中的条件
    169             else:
    170                 raise KeyError('错误,没有选择对象!')
    171 
    172             if hasattr(admin_obj, action):
    173                 action_func = getattr(admin_obj, action)  # 如果admin_obj 对象中有属性action 则打印self.action的值,否则打印'not find'
    174                 request._admin_action = action  # 添加action内容
    175                 print(request._admin_action, action, '<--------')
    176             return action_func(request, selected_objs)
    177     # ————————24PerfectCRM实现King_admin自定义操作数据————————
    178 
    179 
    180     # ————————09PerfectCRM实现King_admin显示注册表的内容————————
    181     admin_obj.querysets = admin_obj.model.objects.all()  # 取数据 传到 前端
    182     # ————————09PerfectCRM实现King_admin显示注册表的内容————————
    183 
    184     # ————————11PerfectCRM实现King_admin分页显示条数————————
    185     # from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger  # 分页功能#放在顶上导入
    186     obj_list = admin_obj.model.objects.all()  # 取数据 传到 前端  #base_admin  #获取传过来的所有对象
    187 
    188     # ————————13PerfectCRM实现King_admin分页页数————————
    189     queryset, condtions = filter_querysets(request, obj_list)  # base_admin   # 调用条件过滤
    190     # ————————13PerfectCRM实现King_admin分页页数————————
    191 
    192     # ————————18PerfectCRM实现King_admin搜索关键字————————
    193     queryset = get_queryset_search_result(request, queryset, admin_obj)  ##搜索后
    194     # ————————18PerfectCRM实现King_admin搜索关键字————————
    195 
    196     # ————————26PerfectCRM实现King_admin自定义排序————————
    197     sorted_queryset = get_orderby(request, queryset, admin_obj)  # 排序后的结果
    198     # ————————17PerfectCRM实现King_admin单列排序————————
    199     # sorted_queryset = get_orderby(request, queryset) #排序后的结果
    200     # ————————15PerfectCRM实现King_admin多条件过滤————————
    201     # paginator = Paginator(obj_list,admin_obj.list_per_page)  #kingadmin里class CustomerAdmin(BaseAdmin):
    202     # paginator = Paginator(queryset, admin_obj.list_per_page)
    203     # ————————15PerfectCRM实现King_admin多条件过滤————————
    204     paginator = Paginator(sorted_queryset, admin_obj.list_per_page)
    205     # ————————17PerfectCRM实现King_admin单列排序————————
    206     # ————————26PerfectCRM实现King_admin自定义排序————————
    207 
    208 
    209     page = request.GET.get('page')
    210     try:
    211         objs = paginator.page(page)  # 当前的页面的数据
    212     except PageNotAnInteger:
    213         # 如果页面不是一个整数,交付第一页。
    214         objs = paginator.page(1)
    215     except EmptyPage:
    216         # 如果页面的范围(例如9999),交付最后一页的搜索结果。
    217         objs = paginator.page(paginator.num_pages)
    218     admin_obj.querysets = objs  # base_admin
    219 
    220     # ————————13PerfectCRM实现King_admin分页页数————————
    221     admin_obj.filter_condtions = condtions  # base_admin
    222     # ————————13PerfectCRM实现King_admin分页页数————————
    223 
    224     # ————————11PerfectCRM实现King_admin分页显示条数————————
    225 
    226     return render(request, "king_admin/table_data_list.html", locals())
    227 
    228 
    229 # ————————08PerfectCRM实现King_admin显示注册表的字段表头————————
    230 
    231 
    232 
    233 
    234 # ————————17PerfectCRM实现King_admin单列排序————————
    235 # def get_orderby(request,queryset):
    236 # order_by_key = request.GET.get("_o")   #获取URL里有没有("_o") <a href="?_o={{ column }}">{{ column }}</a>
    237 # #页面刚开始没有这个值
    238 # if order_by_key != None:  #有("_o")这个值 就进行排序
    239 #     query_res = queryset.order_by(order_by_key)
    240 # else: #没有就不排序,直接返回
    241 #     query_res = queryset
    242 # return query_res     #排序时会错
    243 
    244 # orderby_key = request.GET.get("_o")
    245 # if orderby_key:
    246 #     return  queryset.order_by(orderby_key)
    247 # return  queryset
    248 
    249 # 在table_data_list添加
    250 # def table_data_list(request,app_name,model_name): #详细列表
    251 # sorted_queryset = get_orderby(request, queryset)
    252 # 在filter_querysets添加
    253 # if k == "page"or k == "_o": #保留的分页关键字 和  排序关键字
    254 # ————————17PerfectCRM实现King_admin单列排序————————
    255 
    256 # ————————26PerfectCRM实现King_admin自定义排序————————
    257 def get_orderby(request, queryset, admin_obj):
    258     orderby_key = request.GET.get("_o")
    259     # order_by_key1=order_by_key.strip()
    260     if orderby_key:  # 有获取到字段
    261         query_res = queryset.order_by(orderby_key.strip())  # .strip()默认删除空白符(包括'
    ', '
    ',  '	',  ' ')
    262     else:
    263         if admin_obj.ordering:  # 查看kingadmin‘有没有    ordering = '-qq'  # 自定义排序
    264             query_res = queryset.order_by("%s" % admin_obj.ordering)
    265         else:
    266             query_res = queryset.order_by('-id')  # 默认倒序
    267     return query_res
    268 
    269 
    270 # 在table_data_list添加
    271 # def table_data_list(request,app_name,model_name): #详细列表
    272 # sorted_queryset = get_orderby(request, queryset, admin_obj)  # 排序后的结果
    273 # ————————26PerfectCRM实现King_admin自定义排序————————
    274 
    275 
    276 # ————————18PerfectCRM实现King_admin搜索关键字————————
    277 from django.db.models import Q
    278 
    279 
    280 def get_queryset_search_result(request, queryset, admin_obj):
    281     search_key = request.GET.get("_q", "")  # 取定义名,默认为空
    282     q_obj = Q()  # 多条件搜索 #from django.db.models import Q
    283     q_obj.connector = "OR"  # or/或 条件
    284     for column in admin_obj.search_fields:  # 搜索目标crm/kingadmin里class CustomerAdmin(BaseAdmin):search_fields = ('name','qq',)
    285         q_obj.children.append(("%s__contains" % column, search_key))  # 运态添加多个条件
    286     res = queryset.filter(q_obj)  # 对数据库进行条件搜索
    287     return res  # 返回结果
    288 
    289 
    290 # 在table_data_list添加
    291 # def table_data_list(request,app_name,model_name): #详细列表
    292 #      queryset = get_queryset_search_result(request,queryset,admin_obj)
    293 # ————————18PerfectCRM实现King_admin搜索关键字————————
    294 
    295 
    296 # ————————19PerfectCRM实现King_admin数据修改————————
    297 from  king_admin import forms
    298 
    299 
    300 # 修改内容
    301 # def table_change(request,app_name,model_name):
    302 #     obj_form = forms.CustomerModelForm()  #创建一个空表单
    303 #     return render(request,"kingadmin/table_change.html",locals())
    304 @login_required  # 登陆后页面才能访问
    305 @check_permission #权限控制
    306 def table_change(request, app_name, model_name, obj_id):
    307     admin_obj = base_admin.site.registered_sites[app_name][model_name]  # 获取表对象
    308     # kingadmin/forms.py里def CreateModelForm(request,admin_obj):
    309     model_form = forms.CreateModelForm(request, admin_obj=admin_obj)  ##modelform 生成表单 加验证
    310     # obj_form = model_form()  # 表单
    311     obj = admin_obj.model.objects.get(id=obj_id)  # 根据ID获取数据记录
    312 
    313     # ————————28PerfectCRM实现King_admin编辑限制————————
    314     # ————————20PerfectCRM实现King_admin数据修改美化————————
    315     # #面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
    316     # obj_form = model_form(instance=obj)  # 数据传入表单
    317 
    318     if request.method == "GET":  # 如果是 GET 表示 是添加记录
    319         obj_form = model_form(instance=obj)  # 数据传入表单
    320     elif request.method == "POST":  # 如果是 POST 表示 是修改后的数据
    321         obj_form = model_form(instance=obj, data=request.POST)  # 更新数据
    322         if obj_form.is_valid():
    323             obj_form.save()
    324     # ————————20PerfectCRM实现King_admin数据修改美化————————
    325     # ————————28PerfectCRM实现King_admin编辑限制————————
    326 
    327     return render(request, "king_admin/table_change.html", locals())
    328 
    329 
    330 # ————————19PerfectCRM实现King_admin数据修改————————
    331 
    332 
    333 # ————————21PerfectCRM实现King_admin查看页面美化————————
    334 # 单个具体app页面
    335 @login_required  # 登陆后页面才能访问
    336 def table_index(request, app_name):
    337     bases = base_admin.site.registered_sites[app_name]  # 取出对应app对象
    338     return render(request, 'king_admin/table_index.html', {"site": bases, 'app_name': app_name})
    339 
    340 
    341 # ————————21PerfectCRM实现King_admin查看页面美化————————
    342 
    343 # ————————22PerfectCRM实现King_admin数据添加————————
    344 from django.shortcuts import redirect  # kingadmin添加内容
    345 
    346 
    347 @login_required  # 登陆后页面才能访问
    348 @check_permission #权限控制
    349 def table_add(request, app_name, model_name):
    350     admin_obj = base_admin.site.registered_sites[app_name][model_name]  # 获取表对象
    351     # ————————32PerfectCRM实现King_admin添加不进行限制————————
    352     admin_obj.is_add_form = True  # 表示为新增表单
    353     # ————————32PerfectCRM实现King_admin添加不进行限制————————
    354     model_form = forms.CreateModelForm(request, admin_obj=admin_obj)  ##modelform 生成表单 加验证
    355     if request.method == "GET":
    356         obj_form = model_form()  # 跳转过来的为空
    357     elif request.method == "POST":
    358         obj_form = model_form(data=request.POST)  # 创建数据
    359 
    360         # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
    361         password = request.POST.get('password')  # 取前端输入的密码
    362         email = request.POST.get('email')  # 取前端输入的邮箱
    363         # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
    364 
    365         if obj_form.is_valid():
    366             # ————————32PerfectCRM实现King_admin添加不进行限制————————
    367             # obj_form.save()
    368             try:
    369                 obj_form.save()  # 表单验证通过保存
    370             except Exception as e:
    371                 return redirect("/king_admin/%s/%s/" % (app_name, model_name))  # 转到之前的页面
    372                 # ————————32PerfectCRM实现King_admin添加不进行限制————————
    373         if not obj_form.errors:  # 没有错误返回原来的页面
    374 
    375             # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
    376             if email:
    377                 obj = admin_obj.model.objects.filter(email=email).first()  # 对象
    378                 obj.set_password(password)  # 加密
    379             try:
    380                 obj.save()  # 表单验证通过保存
    381             except Exception as e:
    382                 return redirect("/king_admin/%s/%s/" % (app_name, model_name))
    383             # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
    384 
    385             # from django.shortcuts import redirect
    386             return redirect("/king_admin/%s/%s/" % (app_name, model_name))
    387     return render(request, "king_admin/table_add.html", locals())
    388 
    389 
    390 # ————————22PerfectCRM实现King_admin数据添加————————
    391 
    392 
    393 # ————————23PerfectCRM实现King_admin数据删除————————
    394 @login_required  # 登陆后页面才能访问
    395 @check_permission #权限控制
    396 def table_delete(request, app_name, model_name, obj_id):
    397     admin_obj = base_admin.site.registered_sites[app_name][model_name]  # 表类
    398     objs=admin_obj.model.objects.filter(id=obj_id)#类的对象
    399 
    400     # ————————33PerfectCRM实现King_admin编辑整张表限制————————
    401     # if request.method=='POST':
    402     #     objs.delete()#删除
    403     #     return redirect("/king_admin/%s/%s/" % (app_name,model_name))#转到列表页面
    404 
    405     app_name=app_name
    406     if admin_obj.readonly_table:
    407         errors={'锁定的表单':'该表单:<%s>,已经锁定,不能删除当前记录!'%model_name}
    408     else:
    409         errors={}
    410     if request.method=='POST':
    411         if  not admin_obj.readonly_table:
    412             objs.delete()#删除
    413             return redirect("/king_admin/%s/%s/" % (app_name,model_name))#转到列表页面
    414     # ————————33PerfectCRM实现King_admin编辑整张表限制————————
    415 
    416 
    417     return render(request, "king_admin/table_delete.html", locals())  # locals 返回一个包含当前范围的局部变量字典。
    418 
    419 
    420 # ————————23PerfectCRM实现King_admin数据删除————————
    421 
    422 # ————————36PerfectCRM实现King_admin密码修改————————
    423 # 密码修改
    424 @login_required  # 登陆后页面才能访问
    425 @check_permission #权限控制
    426 def password_reset(request, app_name, model_name, obj_id):
    427     admin_obj = base_admin.site.registered_sites[app_name][model_name]  # 表类
    428     model_form = forms.CreateModelForm(request, admin_obj=admin_obj)  # modelform 生成表单 加验证
    429     obj = admin_obj.model.objects.get(id=obj_id)  # 类表的对象
    430     errors = {}  # 错误提示
    431     if request.method == 'POST':
    432         _password1 = request.POST.get('password1')  # 获取页面输入的值
    433         _password2 = request.POST.get('password2')  # 获取页面输入的值
    434         if _password1 == _password2:
    435             if len(_password1) > 5:
    436                 obj.set_password(_password1)  # 继承Django方法 #加密
    437                 obj.save()  # 保存
    438                 return redirect(request.path.rstrip('password/') + ('/change/'))  # 替换URL名
    439             else:
    440                 errors['password_too_short'] = '必须不少于6字符'
    441         else:
    442             errors['invalid_password'] = '两次输入的密码不一样'  # 密码不一致
    443 
    444     return render(request, "king_admin/password_reset.html", locals())  # locals 返回一个包含当前范围的局部变量字典。
    445 
    446 
    447 # ————————36PerfectCRM实现King_admin密码修改————————
    448 
    449 # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
    450 def password_add(request, app_name, model_name):
    451     return redirect("/king_admin/%s/%s/add/" % (app_name, model_name))  # 转到添加页面
    452     # ————————37PerfectCRM实现King_admin添加用户时密码加密————————
    # views

      1 # sales_views.py
      2 # ————————47PerfectCRM实现CRM客户报名流程————————
      3 from django.db import IntegrityError  # 主动捕捉错误信息
      4 from django.shortcuts import render  # 页面返回
      5 from crm import models  # 数据库
      6 from bpm.bpm_auxiliary import bpm_forms  # 自定制 forms
      7 from  django.contrib.auth.decorators import login_required  # 登陆后页面才能访问
      8 
      9 # ————————47PerfectCRM实现CRM客户报名流程————————
     10 from django.core.mail import send_mail
     11 # send_mail的参数分别是  邮件标题,邮件内容,发件箱(settings.py中设置过的那个),收件箱列表(可以发送给多个人),失败静默(若发送失败,报错提示我们)
     12 import random
     13 import datetime  # 获取时间#登陆过期
     14 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     15 from permissions.permission import check_permission #权限控制
     16 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     17 # 发送邮件的功能 #验证码#密码
     18 class stmp():
     19     def __init__(self):
     20         self.emaillist = []  # 发送给谁
     21         self.code = None  # 验证码#密码
     22 
     23     def stmps(self, request, email, msg_mail):  # 传参数#页面,session #邮箱,发送给谁 #内容
     24         self.emaillist.append(email)  # 将邮箱地址添加到调用Django发送邮件功能
     25         # ——————生成验证码——————
     26         _letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
     27         _upper_cases = _letter_cases.upper()  # 大写字母
     28         _numbers = ''.join(map(str, range(3, 10)))  # 数字
     29         chars = ''.join((_letter_cases, _upper_cases, _numbers))  # 变成一条字符串
     30         list = random.sample(chars, 4)  # 从一条字符串随机选4个字符变成列表
     31         self.code = ''.join(list)  # 列表变字符串
     32         # ——————生成验证码——————
     33         # ——————调用Django发送邮件——————
     34         title = 'PerfectCRM项目自动邮件:%s' % self.code  # 邮件标题#防止一样的内容被邮箱屏蔽
     35         send_mail(title,  # 邮件标题
     36                   msg_mail,  # 验证码内容
     37                   'perfectcrm@sina.cn',  # 发送的邮箱  #根据情况重新配置
     38                   self.emaillist,  # 接受的邮箱
     39                   fail_silently=False,  # 静默,抛出异常
     40                   )
     41         print('发送邮件成功!没收到要换标题!检查发送邮箱的配置!')
     42         # ——————调用Django发送邮件——————
     43 # ————————47PerfectCRM实现CRM客户报名流程————————
     44 # ————————47PerfectCRM实现CRM客户报名流程————————
     45 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
     46 import random  # 随机
     47 import string  # 字母 数字
     48 from django.core.cache import cache  # 缓存
     49 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
     50 
     51 # 报名填写 销售
     52 @login_required  # 登陆后页面才能访问
     53 @check_permission #权限控制
     54 def enrollment(request, customer_id):
     55     msgs = {}  # 错误信息
     56     customer_obj = models.Customer.objects.get(id=customer_id)  # 取到客户信息记录 #返回到页面#报名人
     57     consultant_obj = models.UserProfile.objects.get(id=request.user.id)  # 报名课程顾问
     58 
     59     stmp_mail = {}  # 邮件发送成功
     60     stmpemail = stmp()  # 实例化发送邮件的功能
     61     email = request.POST.get('email')  # 让页面POST提交的值,在页面GET后仍然存在显示
     62     if request.method == "POST":
     63         enroll_form = bpm_forms.EnrollmentForm(request.POST)  # 获取数据
     64         if enroll_form.is_valid():  # 表单验证
     65 
     66             # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
     67             # msg = "http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/"
     68             msg = "http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/{random_str}/ "
     69             random_str = ''.join(random.sample(string.ascii_lowercase + string.digits, 8))  # 生成8位随机字符串 #URL使用
     70             url_str = '''customer/registration/{enroll_obj_id}/{random_str}/'''  # 报名链接
     71             # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
     72 
     73             try:
     74                 enroll_form.cleaned_data['customer'] = customer_obj  # 添加学员对象 记录 #报名人
     75                 enroll_form.cleaned_data['consultant'] = consultant_obj  # 报名课程顾问
     76                 enroll_obj = models.Enrollment.objects.create(**enroll_form.cleaned_data)  # 创建记录
     77 
     78                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
     79                 # msgs['msg']=msg.format(enroll_obj_id=enroll_obj.id)#报名记录对应的id,随机字符串,报名链接
     80                 sort_url = enroll_obj.id  # 获取报名表对应的ID
     81                 cache.set(enroll_obj.id, random_str, 61000)  # 加入过期时间   #URL使用    # cache缓存
     82                 msgs['msg'] = msg.format(enroll_obj_id=enroll_obj.id, random_str=random_str)  # 报名记录对应的id,随机字符串,报名链接
     83                 url_str = url_str.format(enroll_obj_id=enroll_obj.id, random_str=random_str)  # 报名链接
     84                 print(url_str)
     85                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
     86             except IntegrityError as e:
     87                 # 取到这条记录
     88                 enroll_obj = models.Enrollment.objects.get(customer_id=customer_obj.id,
     89                                                            enrolled_class_id=enroll_form.cleaned_data[
     90                                                                'enrolled_class'].id)
     91 
     92                 # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
     93                 if enroll_obj.contract_agreed:#学员已经同意合同,提交了身份证
     94                     #return redirect('/crm/contract_review/%s/'%enroll_obj.id)#跳转到审核页面
     95                     return render(request,'bpm_sales/contract_prompt.html',locals())#跳转提示页面
     96                 # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
     97 
     98                 enroll_form.add_error('__all__', '记录已经存在,不能重复创建!')
     99 
    100                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    101                 # msgs['msg']=msg.format(enroll_obj_id=enroll_obj.id)#报名记录对应的id
    102                 cache.set(enroll_obj.id, random_str, 61000)  # 加入过期时间  #URL使用    # cache缓存
    103                 msgs['msg'] = msg.format(enroll_obj_id=enroll_obj.id, random_str=random_str)  # 报名记录对应的id
    104                 url_str = url_str.format(enroll_obj_id=enroll_obj.id, random_str=random_str)  # 报名链接
    105                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    106 
    107             if email:
    108                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    109                 # msg_mail = "http://127.0.0.1:8000/bpm/customer/registration/%s" %enroll_obj.id
    110                 msg_mail = "http://127.0.0.1:8000/bpm/customer/registration/%s/%s" %(enroll_obj.id,random_str)
    111                 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    112                 stmpemail.stmps(request, email, msg_mail)  # 发送邮件
    113                 stmp_mail['ok'] = "邮件已发送成功!"
    114 
    115     else:
    116         enroll_form = bpm_forms.EnrollmentForm()  # modelform表单
    117     return render(request, 'bpm_sales/enrollment.html', locals())
    118 # ————————47PerfectCRM实现CRM客户报名流程————————
    119 
    120 
    121 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
    122 #学员合同签定
    123 
    124 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
    125 import os
    126 from PerfectCRM import settings
    127 import json
    128 # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
    129 
    130 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    131 from django.shortcuts import HttpResponse #页面返回
    132 # def stu_registration(request,enroll_id):
    133 def stu_registration(request,enroll_id,random_str):
    134     # enroll_obj=models.Enrollment.objects.get(id=enroll_id)#获取报名记录
    135     if cache.get(enroll_id) == random_str:  # 判断链接失效了没有
    136         enroll_obj = models.Enrollment.objects.get(id=enroll_id)  # 报名记录
    137 # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    138 
    139         # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
    140         enrolled_path='%s/%s/'%(settings.ENROLLED_DATA,enroll_id)#证件上传路径
    141         img_file_len=0  #文件
    142         if os.path.exists(enrolled_path):#判断目录是否存在
    143             img_file_list=os.listdir(enrolled_path)#取目录 下的文件
    144             img_file_len=len(img_file_list)
    145         # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
    146 
    147     # ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————
    148         # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    149         if request.method == "POST":
    150 
    151             # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
    152             ret=False
    153             data=request.POST.get('data')
    154             if data:#如果有删除动作
    155                 del_img_path="%s/%s/%s"%(settings.ENROLLED_DATA,enroll_id,data)#路径
    156                 print(del_img_path,'=-=-=-=-=-=')
    157                 os.remove(del_img_path)
    158                 ret=True
    159                 return HttpResponse(json.dumps(ret))
    160             if request.is_ajax():#ajax上传图片 #异步提交
    161                 print('ajax上传图片 #异步提交中。。。 ',request.FILES)
    162                 enroll_data_dir="%s/%s"%(settings.ENROLLED_DATA,enroll_id)#路径  #重要信息不能放在静态文件中
    163                 if not os.path.exists(enroll_data_dir):#如果不存目录
    164                     os.makedirs(enroll_data_dir,exist_ok=True)#创建目录
    165                 for k,file_obj in request.FILES.items():   #循环字典 #上传的文件
    166                     with open("%s/%s"%(enroll_data_dir,file_obj.name),'wb') as f: #打开一个文件#路径#获取文件名
    167                         for chunk in file_obj.chunks():#循环写入文件 # chunks块
    168                             f.write(chunk)  #保存文件
    169                 return HttpResponse('上传完成!')
    170             # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
    171 
    172             customer_form = bpm_forms.CustomerForm(request.POST, instance=enroll_obj.customer)  # 生成表单验证
    173             if customer_form.is_valid():  # 表单验证通过
    174                 customer_form.save()  # 保存
    175                 enroll_obj.contract_agreed = True  # 同意协议
    176                 enroll_obj.save()  # 保存
    177                 status = 1  # 修改报名状态 # 1 已经报名
    178                 return render(request, 'bpm_sales/stu_registration.html', locals())
    179 
    180         else:
    181             if enroll_obj.contract_agreed == True:  # 如果协议已经签订
    182                 status = 1  # 修改报名状态 # 1 已经报名
    183             else:
    184                 status = 0
    185             customer_form = bpm_forms.CustomerForm(instance=enroll_obj.customer)  # 生成表单
    186     # customer_form = bpm_forms.CustomerForm(instance=enroll_obj.customer)  # 生成表单
    187     # ————————49PerfectCRM实现CRM客户报名流程学生合同表单验证————————
    188 
    189         return render(request,'bpm_sales/stu_registration.html',locals())
    190         # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    191 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
    192     # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    193     else:
    194         return HttpResponse('链接失效,非法链接,请自重!')
    195     # ————————50PerfectCRM实现CRM客户报名流程学生合同URL随机码————————
    196 
    197 
    198 # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
    199 from django.shortcuts import redirect
    200 #查询流程提示页面
    201 def contract_prompt(request,enroll_id):
    202     enroll_obj=models.Enrollment.objects.get(id=enroll_id)#取对象
    203     enroll_form= bpm_forms.EnrollmentForm(instance=enroll_obj)#报名表对象
    204     customers_form= bpm_forms.CustomerForm(instance=enroll_obj.customer)#学员的信息
    205     return render(request,'bpm_sales/contract_prompt.html',locals())
    206 
    207 # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    208 from bpm.bpm_auxiliary.pagination import Page #分页
    209 # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    210 # #待审核
    211 @login_required # 登陆后页面才能访问
    212 @check_permission #权限控制
    213 def not_audit(request):
    214     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    215     # sign=models.Enrollment.objects.all()#所有的报名表
    216     # print(sign,'sign----->')
    217     sign=models.Enrollment.objects.filter(contract_agreed=True,contract_approved=False).all()#所有的报名表
    218 
    219     page = Page(request.GET.get('p', 1), len(sign)) #当前页数 默认为1 #总数量
    220     sign = sign[page.start:page.end]  # 切片取当前页的数据
    221     page_str = page.page_str('/bpm/not_audit/')  #总页数 传入url
    222     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    223     return render(request, 'bpm_sales/not_audit.html', locals())#
    224 
    225 #审核合同
    226 @login_required # 登陆后页面才能访问
    227 @check_permission #权限控制
    228 def contract_review(request,enroll_id):
    229     enroll_obj=models.Enrollment.objects.get(id=enroll_id)#取对象
    230     contract_review = request.user.name #当前登陆人 #合同审核人
    231     #payment_form=forms.PaymentForm()#生成表单
    232     enroll_form= bpm_forms.EnrollmentForm(instance=enroll_obj)#报名表对象
    233     customer_form= bpm_forms.CustomerForm(instance=enroll_obj.customer)#学员的信息
    234     enrolled_path='%s/%s/'%(settings.ENROLLED_DATA,enroll_id)#证件上传路径
    235     if os.path.exists(enrolled_path):#判断目录是否存在
    236         file_list=os.listdir(enrolled_path)#取目录 下的文件
    237         imgs_one=file_list[0]  #图片1
    238         imgs_two=file_list[1]  #图片2
    239     if request.method=="POST":
    240         enroll_obj.contract_approved = True  # 审核通过
    241         enroll_obj.save() #保存
    242         enroll = models.Enrollment.objects.filter(id=enroll_id).update(contract_review=contract_review)#合同审核人
    243         print('审核通过。。。')
    244         return redirect('/bpm/not_audit/')#跳转到待审核
    245     return render(request, 'bpm_sales/contract_review.html', locals())#
    246 #驳回合同
    247 def enrollment_rejection(request,enroll_id):
    248     enroll_obj=models.Enrollment.objects.get(id=enroll_id)#报名表的对象
    249     enroll_obj.contract_agreed=False#修改学员已经同意核同
    250     enroll_obj.save() #保存
    251     return redirect('/bpm/customer/%s/enrollment/'%enroll_obj.customer.id)#跳转到enrollment_rejection
    252 # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
    # sales_views.py

     1 # financial_views.py
     2 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
     3 from crm import models #数据库
     4 from django.shortcuts import redirect,render   #页面返回
     5 from bpm.bpm_auxiliary import bpm_forms   #自定制 forms
     6 from  django.contrib.auth.decorators import login_required # 登陆后页面才能访问
     7 
     8 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     9 from permissions.permission import check_permission #权限控制
    10 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
    11 
    12 # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    13 from bpm.bpm_auxiliary.pagination import Page #分页
    14 # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    15 
    16 # #待缴费
    17 @login_required  # 登陆后页面才能访问
    18 @check_permission #权限控制
    19 def not_payment(request):
    20 
    21     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    22     # sign=models.Enrollment.objects.all()#所有的报名表
    23     sign=models.Enrollment.objects.filter(contract_approved=True,Pay_cost=False).all()#所有的报名表
    24 
    25     page = Page(request.GET.get('p', 1), len(sign)) #当前页数 默认为1 #总数量
    26     sign = sign[page.start:page.end]  # 切片取当前页的数据
    27     page_str = page.page_str('/bpm/not_payment/')  #总页数 传入url
    28     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    29 
    30     return render(request, 'bpm_financial/not_payment.html', locals())#
    31 # 已缴费
    32 @login_required  # 登陆后页面才能访问
    33 @check_permission #权限控制
    34 def already_payment(request):
    35 
    36     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    37     # sign=models.Enrollment.objects.all()#所有的报名表
    38     sign=models.Enrollment.objects.filter(contract_approved=True,Pay_cost=True).all()#所有的报名表
    39 
    40     page = Page(request.GET.get('p', 1), len(sign)) #当前页数 默认为1 #总数量
    41     sign = sign[page.start:page.end]  # 切片取当前页的数据
    42     page_str = page.page_str('/bpm/already_payment/')  #总页数 传入url
    43     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    44 
    45     return render(request, 'bpm_financial/already_payment.html', locals())#
    46 #缴费视图
    47 @login_required # 登陆后页面才能访问
    48 @check_permission #权限控制
    49 def payment(request,enroll_id):
    50     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    51     # sign=models.Payment.objects.all()#所有的报名表#前端对比用户#缴费记录
    52     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    53     enroll_obj=models.Enrollment.objects.get(id=enroll_id)#取对象
    54     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    55     sign=models.Payment.objects.filter(customer=enroll_obj.customer).all()#所有的报名表#前端对比用户#缴费记录
    56     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    57     errors={}  #错误信息
    58     if request.method=="POST":
    59         payment_amount=request.POST.get('amount')#缴费金额
    60         consultant = models.UserProfile.objects.get(id=request.user.id)  #财务人员 #当前登陆人
    61         if payment_amount:
    62             payment_amount=int(payment_amount)  #转数字类型
    63             if payment_amount<500:
    64                 errors['err']='缴费金额不得低于500元!'
    65             else: #生成forms
    66                 payment_obj=models.Payment.objects.create(
    67                     customer=enroll_obj.customer,##客户表 学员
    68                     course=enroll_obj.enrolled_class.course,#所报课程
    69                     consultant=consultant,# 财务人员
    70                     amount=payment_amount,#缴费金额
    71                 )
    72                 enroll_obj.Pay_cost=True#已缴费
    73                 enroll_obj.save()   #保存
    74                 enroll_obj.customer.status=0#修改报名状态 为已报名#根据数据库
    75                 enroll_obj.customer.save()  #保存
    76                 return redirect('/bpm/not_payment')#客户表
    77         else:
    78             errors['err']='金额不能为空!'
    79     else:
    80         payment_form= bpm_forms.PaymentForm()#生成表单
    81 
    82     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    83     page = Page( request.GET.get( 'p', 1 ), len( sign ) )  # 当前页数 默认为1 #总数量
    84     sign = sign[page.start:page.end]  # 切片取当前页的数据
    85     page_str = page.page_str( '/bpm/payment/%s/'%enroll_id )  # 总页数 传入url
    86     # ————————68PerfectCRM实现CRM业务流程(bpm)报名缴费分页————————
    87 
    88     return render(request, 'bpm_financial/payment.html', locals())
    89 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
    # financial_views.py

      1 # student_views.py
      2 # ————————60PerfectCRM实现CRM学生上课记录————————
      3 from django.shortcuts import render #页面返回
      4 from crm import models #数据库
      5 from  django.contrib.auth.decorators import login_required # 登陆后页面才能访问
      6 
      7 # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
      8 from bpm.bpm_auxiliary.pagination import Page #分页
      9 # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     10 
     11 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     12 from permissions.permission import check_permission #权限控制
     13 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     14 
     15 #学生报名的课程
     16 @login_required # 登陆后页面才能访问
     17 @check_permission #权限控制
     18 def student_course(request):
     19     if request.user.stu_account:
     20         enrollmentlist=request.user.stu_account.enrollment_set.all()#根据账号表关联的ID获取06学员报名信息表
     21 
     22         # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     23         page = Page(request.GET.get('p', 1), len(enrollmentlist)) #当前页数 默认为1 #总数量
     24         enrollmentlist = enrollmentlist[page.start:page.end]  # 切片取当前页的数据
     25         page_str = page.page_str('/bpm/student_course/')  #总页数 传入url
     26         # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     27 
     28     return  render(request, 'bpm_student/student_course.html', locals())
     29 
     30 #学生上课记录列表
     31 @login_required # 登陆后页面才能访问
     32 @check_permission #权限控制
     33 def studyrecords(request,enroll_obj_id):
     34     enroll_obj=models.Enrollment.objects.get(id=enroll_obj_id)#根据ID获取06学员报名信息表
     35     studyrecordlist=enroll_obj.studyrecord_set.all()#根据06学员报名信息表的ID获取09学习纪录
     36 
     37     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     38     page = Page(request.GET.get('p', 1), len(studyrecordlist)) #当前页数 默认为1 #总数量
     39     studyrecordlist = studyrecordlist[page.start:page.end]  # 切片取当前页的数据
     40     page_str = page.page_str('/bpm/studyrecords/%s/'%enroll_obj_id)  #总页数 传入url
     41     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     42 
     43     return render(request,'bpm_student/studyrecords.html',locals())
     44 
     45 # ————————60PerfectCRM实现CRM学生上课记录————————
     46 
     47 # ————————61PerfectCRM实现CRM学生上传作业————————
     48 from django.contrib.auth.decorators import login_required #登陆才能访问
     49 from PerfectCRM import settings #静态配置文件  #作业上传 # 上传路径
     50 import os,json,time #系统操作
     51 from django.shortcuts import HttpResponse #页面返回
     52 from django.shortcuts import redirect #页面返回
     53 #作业详情
     54 @login_required#登陆才能访问
     55 @check_permission #权限控制
     56 def homework_detail(request,enroll_obj_id,studyrecord_id):
     57     studyrecord_obj=models.StudyRecord.objects.get(id=studyrecord_id)#取学习记录 对象
     58     enroll_obj=models.Enrollment.objects.get(id=enroll_obj_id)#取班级对象
     59 
     60     #               作业根目录    班级ID      上课记录ID               学习记录ID
     61     homework_path="{base_dir}/{class_id}/{course_record_id}/{studyercord_id}/".format(
     62         base_dir=settings.HOMEWORK_DATA, #静态配置文件
     63         class_id=studyrecord_obj.student.enrolled_class_id,#09学习纪录#学生名字#所报班级ID号
     64         course_record_id=studyrecord_obj.course_record_id,#09学习纪录#每节课上课纪录表
     65         studyercord_id=studyrecord_obj.id##09学习纪录
     66     )
     67     print('homework_path路径:',studyrecord_obj.student.enrolled_class_id,studyrecord_obj.course_record_id,studyrecord_obj.id)
     68 
     69     if os.path.exists(homework_path):#判断目录是否存在
     70         file_lists = []  # 已经上传的文件列表
     71         for file_name in os.listdir( homework_path ):
     72             f_path = '%s/%s' % (homework_path, file_name)  # 文件名字
     73             modify_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.gmtime( os.stat( f_path ).st_mtime ) )  # 文件上传时间
     74             file_lists.append( [file_name, os.stat( f_path ).st_size, modify_time] )  # 添加到文件列表#文件名字#文件大小文件上传时间
     75 
     76 
     77     if request.method=="POST":#上传
     78         ret=False
     79         data=request.POST.get('data') #ajax
     80         if data:#如果有删除动作
     81             del_f_path="%s/%s"%(homework_path,data)#文件路径
     82             print('删除文件,路径:',del_f_path)
     83             os.remove(del_f_path) #删除
     84             ret=True
     85             return HttpResponse(json.dumps(ret))#ret=False
     86         if request.is_ajax():  # ajax上传图片 #异步提交
     87             print("POST",request.POST)
     88             if not os.path.isdir( homework_path ):  # 没有目录 #isdir返回true,如果路径名是指现有的目录。
     89                 os.makedirs( homework_path, exist_ok=True )  # 创建目录  
     90             for k,v in request.FILES.items():#上传的文件
     91                 with open('%s/%s'%(homework_path,v.name),'wb') as f:#chunk 写入文件
     92                     for chunk in v.chunks(): #循环写文件
     93                         f.write(chunk)
     94             return HttpResponse( json.dumps( {"status": 0, 'mag': "上传完成!", 'file_lists': file_lists} ) )  # 上传文件返回
     95 
     96     if request.method=="POST":#上传
     97         link = request.POST.get( 'link' )  # 让页面POST提交的值,在页面GET后仍然存在显示
     98         if link:
     99             homework_link=models.StudyRecord.objects.filter( id=studyrecord_id ).update(homework_link=link)
    100             return redirect('/bpm/homework_detail/%s/%s/' %(enroll_obj_id,studyrecord_id) )#跳转到enrollment_rejection
    101     return render(request,'bpm_student/homework_detail.html',locals())
    102 # ————————61PerfectCRM实现CRM学生上传作业————————
    # student_views.py

      1 # teacher_views.py
      2 # ————————62PerfectCRM实现CRM讲师讲课记录————————
      3 from django.contrib.auth.decorators import login_required  # 登陆后页面才能访问
      4 from django.shortcuts import render  #页面返回
      5 
      6 # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
      7 from bpm.bpm_auxiliary.pagination import Page #分页
      8 # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
      9 
     10 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     11 from permissions.permission import check_permission #权限控制
     12 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     13 # 讲师班级
     14 @login_required  # 登陆后页面才能访问
     15 @check_permission #权限控制
     16 def teacher_class(request):
     17     # user_id=request.user.id #当前登陆的ID
     18     # classlist=models.UserProfile.objects.get(id=user_id).classlist_set.all()#讲师所教班级
     19     classes_obj = request.user.classlist_set.all()  # 根据 登陆的ID 获取02班级表
     20 
     21     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     22     page = Page(request.GET.get('p', 1), len(classes_obj)) #当前页数 默认为1 #总数量
     23     classes_obj = classes_obj[page.start:page.end]  # 切片取当前页的数据
     24     page_str = page.page_str('/bpm/teacher_class/')  #总页数 传入url
     25     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     26 
     27     return render( request, 'bpm_teacher/teacher_class.html', locals() )
     28 
     29 # 讲师班级课节详情
     30 @login_required  # 登陆后页面才能访问
     31 @check_permission #权限控制
     32 def teacher_class_detail(request, class_id):
     33     # user_id=request.user.id #当前登陆的ID
     34     # classes_obj=models.UserProfile.objects.get(id=user_id).classlist_set.get(id=class_id)#所选的班级
     35     classes_obj = request.user.classlist_set.get( id=class_id )  # 根据 登陆的ID 获取02班级表
     36     courserecordlist = classes_obj.courserecord_set.all()  # 根据 02班级表的ID 获取09学习纪录
     37 
     38     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     39     page = Page( request.GET.get( 'p', 1 ), len( courserecordlist ) )  # 当前页数 默认为1 #总数量
     40     courserecordlist = courserecordlist[page.start:page.end]  # 切片取当前页的数据
     41     page_str = page.page_str('/bpm/teacher_class_detail/%s/'%class_id) #总页数 传入url
     42     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     43 
     44     return render( request, 'bpm_teacher/teacher_classes_detail.html', locals() )
     45 # ————————62PerfectCRM实现CRM讲师讲课记录————————
     46 
     47 # ————————63PerfectCRM实现CRM讲师下载作业————————
     48 from PerfectCRM import settings  # 系统配置
     49 import os  # 系统操作
     50 # 本节课的学员
     51 @login_required  # 登陆后页面才能访问
     52 @check_permission #权限控制
     53 def teacher_lesson_detail(request, class_id, courserecord_id):
     54     # classes_obj=models.UserProfile.objects.get(id=request.user.id).classlist_set.get(id=class_id)#所选的班级
     55     classes_obj = request.user.classlist_set.get( id=class_id ) # 根据 登陆的ID 获取02班级表
     56     courserecordlist = classes_obj.courserecord_set.get( id=courserecord_id )  # 根据 前端的ID 获取08每节课上课纪录表
     57 
     58     # studyrecord_list=models.CourseRecord.objects.get(id=courserecord_id).studyrecord_set.all()#取本节课所有学员
     59     studyrecord_list = courserecordlist.studyrecord_set.all()  # 根据08每节课上课纪录表 #获取09学习纪录 #取本节课所有学员
     60 
     61     for i in studyrecord_list:  # 循环本节课所有学员 交作业的状态
     62         studyrecord_id = i.id  # 获取本节课所有学员的ID
     63         if studyrecord_id:  # 有获取到ID
     64             HOMEWORK_path = '%s/%s/%s/%s/' % (settings.HOMEWORK_DATA, class_id, courserecord_id, studyrecord_id)  # 作业目录
     65             if os.path.exists( HOMEWORK_path ):  # 判断目录是否存在
     66                 try:#防止后台误删文件
     67                     file_list = os.listdir( HOMEWORK_path )  # 取目录 下的文件
     68                     isfile = os.path.isfile( '%s%s' % (HOMEWORK_path, file_list[0]) )  # 判断是不是文件
     69                     studyrecord_list.filter( id=studyrecord_id ).update( delivery=isfile )  # 更新交付作业状态
     70                 except:
     71                     studyrecord_list.filter( id=studyrecord_id ).update( delivery=False )  # file_list 出错# 更新交付作业状态
     72             else:
     73                 studyrecord_list.filter( id=studyrecord_id ).update( delivery=False )# 更新交付作业状态
     74 
     75     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     76     page = Page( request.GET.get( 'p', 1 ), len( studyrecord_list ) )  # 当前页数 默认为1 #总数量
     77     studyrecord_list = studyrecord_list[page.start:page.end]  # 切片取当前页的数据
     78     page_str = page.page_str('/bpm/teacher_lesson_detail/%s/%s/'%(class_id,courserecord_id)) # 总页数 传入url
     79     # ————————69PerfectCRM实现CRM业务流程(bpm)学生讲师分页————————
     80 
     81     return render( request, 'bpm_teacher/teacher_lesson_detail.html', locals() )
     82 
     83 from django.http import StreamingHttpResponse #页面返回
     84 from crm import models #数据库
     85 from django.shortcuts import redirect #页面返回
     86 # 学员作业下载
     87 @login_required  # 登陆后页面才能访问
     88 @check_permission #权限控制
     89 def howk_down(request, class_id, courserecord_id, studyrecord_id):
     90     HOMEWORK_path = '%s/%s/%s/%s/' % (settings.HOMEWORK_DATA, class_id, courserecord_id, studyrecord_id)  # 作业目录
     91     print( '下载作业目录:', HOMEWORK_path )
     92 
     93     def file_iterator(file_path, chunk_size=512):  # 获取文件 #chunk_size每次读取的大小 #文件迭代器
     94         with open( file_path, 'rb', ) as f:  # 循环打开 文件#以二进制读模式打开
     95             while True:  # 如果有文件
     96                 byte = f.read( chunk_size )  # read读最多大小字节,作为字节返回。#获取文件大小
     97                 if byte:
     98                     yield byte  # 返回 yield 后的值作为第一次迭代的返回值. 循环下一次,再返回,直到没有可以返回的。
     99                 else:
    100                     break  # 没有字节就中止
    101 
    102     if os.path.exists( HOMEWORK_path ):  # 判断目录是否存在
    103         try:#防止后台误删文件
    104             file_list = os.listdir( HOMEWORK_path )  # 取目录 下的文件
    105             print( '文件名:', file_list, type( file_list ) )
    106             file_path = '%s%s' % (HOMEWORK_path, file_list[0])  # 下载文件路径
    107             print( '下载文件路径:', file_path )
    108             response = StreamingHttpResponse( file_iterator( file_path ) )  # StreamingHttpResponse是将文件内容进行流式传输
    109             response['Content-Type'] = 'application/octet-stream'  # 文件类型 #应用程序/octet-stream.*( 二进制流,不知道下载文件类型)
    110             file_name = 'attachment;filename=%s' % file_list[0]  # 文件名字# 支持中文
    111             response['Content-Disposition'] = file_name.encode()  # 支持中文#编码默认encoding='utf-8'
    112             return response  # 返回下载 请求的内容
    113         except:
    114             models.StudyRecord.objects.get( id=studyrecord_id ).update( delivery=False )  # 更新交付作业状态 # file_list 出错
    115     return redirect( '/bpm/teacher_lesson_detail/%s/%s/' % (class_id, courserecord_id) )  # 返回##本节课的学员
    116 # ————————63PerfectCRM实现CRM讲师下载作业————————
    # teacher_views.py

      1 # coursetop_views.py
      2 # ————————64PerfectCRM实现CRM课程排名详情————————
      3 #————班级学生详情——#计算#{学员ID:分数}——#计算 #{学员ID: [分数, 排名] }————#
      4 #班级学生详情#计算#{学员ID:分数}
      5 from django.db.models import Sum #返回数组中所有值的和
      6 def get_course_grades(class_obj):#返回整个班级的成绩
      7     c=models.StudyRecord.objects.filter(course_record__from_class=class_obj).values_list('student')
      8     a=Sum('score')#Sum返回数组中所有值的和   #学习成绩
      9     e=c.annotate(a) #annotate数据库的数据聚合函数
     10     class_grade_dic=dict(e)#{1: 285, 16: 190}#{学员ID:分数}
     11     print( '全班成绩:', class_grade_dic)
     12     return class_grade_dic   #as class_grade_dic
     13 
     14 #班级学生详情#计算 #{学员ID: [分数, 排名] }
     15 def get_course_ranking(class_grade_dic):#返回整个班级的排名数据
     16     ranking_list = sorted(class_grade_dic.items(),key=lambda x:x[1],reverse=True)#进行排序后的列表#以第2个参数对比#倒序
     17     print('成绩排序:',ranking_list)
     18     ranking_dic = {}
     19     for item in ranking_list:
     20         ranking_dic[item[0]] = [item[1], ranking_list.index(item)+1] #循环添加 排名数 到 排序后的列表
     21     print( '全班排名:', ranking_dic)#{1: [285, 1], 10: [280, 2], }#{学员ID: [分数, 排名] }
     22     return ranking_dic
     23 #————班级学生详情——#计算#{学员ID:分数}——#计算 #{学员ID: [分数, 排名] }————#
     24 
     25 from django.contrib.auth.decorators import login_required  # 登陆后页面才能访问
     26 from django.shortcuts import render #页面返回
     27 from crm import models #数据库
     28 # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
     29 from bpm.bpm_auxiliary.pagination import Page #分页
     30 # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
     31 
     32 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     33 from permissions.permission import check_permission #权限控制
     34 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
     35 
     36 #班级学生详情
     37 @login_required  # 登陆后页面才能访问
     38 @check_permission #权限控制
     39 def coursetop_details(request,class_id):
     40     classes_obj = models.ClassList.objects.get(id=class_id)#通过ID获取02班级表
     41     enrollmentlist=classes_obj.enrollment_set.all()#通过班级ID,获取06学员报名信息表
     42 
     43     class_grade_dic=get_course_grades(classes_obj.id)#{学员ID:分数}        #全班成绩 # coursetop_tags.py 根据id 找对应的分数
     44     ranking_dic=get_course_ranking(class_grade_dic)#{学员ID: [分数, 排名] } #全班排名 # coursetop_tags.py 根据id 找对应的排名
     45 
     46     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
     47     page = Page( request.GET.get( 'p', 1 ), len( enrollmentlist ) )  # 当前页数 默认为1 #总数量
     48     enrollmentlist = enrollmentlist[page.start:page.end]  # 切片取当前页的数据
     49     page_str = page.page_str('/bpm/coursetop_details/%s/'%(class_id)) # 总页数 传入url
     50     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
     51 
     52     return render(request,'bpm_coursetop/coursetop_details.html',locals())
     53 # ————————64PerfectCRM实现CRM课程排名详情————————
     54 
     55 
     56 
     57 # ————————65PerfectCRM实现CRM课程分数排名————————
     58 #———— 班级学生详情——#计算 #{排名: (ID, 分数)}#排名查名字————#
     59 def get_ranking_name(class_grade_dic):
     60     lists=[]
     61     ranking_list = sorted(class_grade_dic.items(),key=lambda x:x[1],reverse=True)#进行排序后的列表#以第2个参数对比#倒序
     62     #ranking_list [(1, 285), (10, 280)] #按分高排序的ID顺序
     63     for item in ranking_list:
     64         temp={}
     65         temp[ranking_list.index(item) + 1] = item  # 循环添加 排名数 到 排序后的列表
     66         lists.append(temp)
     67     print( '排名查名字:', lists )#[{1: (1, 285)}, {2: (10, 280)}]#[{排名: (学员ID, 分数)}]
     68     return lists
     69 #———— 班级学生详情——#计算 #{排名: (ID, 分数)}#排名查名字————#
     70 
     71 #班级学生详情#全班成绩排名 #通过#{排名: (ID, 分数)}#排名查名字
     72 @login_required  # 登陆后页面才能访问
     73 @check_permission #权限控制
     74 def coursetop_score(request,class_id):
     75     classes_obj = models.ClassList.objects.get(id=class_id)#通过ID获取02班级表
     76     class_grade_dic=get_course_grades(classes_obj.id)#{学员ID:分数}        #全班成绩
     77     lists=get_ranking_name(class_grade_dic)#计算#[{排名: (学员ID, 分数)}]  #按分高排序的ID顺序
     78 
     79     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
     80     page = Page( request.GET.get( 'p', 1 ), len( lists ) )  # 当前页数 默认为1 #总数量
     81     lists = lists[page.start:page.end]  # 切片取当前页的数据
     82     page_str = page.page_str('/bpm/coursetop_score/%s/'%(class_id)) # 总页数 传入url
     83     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
     84 
     85     return render(request,'bpm_coursetop/coursetop_score.html',locals())
     86 
     87 # ————————65PerfectCRM实现CRM课程分数排名————————
     88 
     89 # ————————66PerfectCRM实现CRM课程作业排名————————
     90 #————#班级学生详情#计算#学员已交作业的数量————#
     91 #班级学生详情#计算#学员已交作业的数量
     92 def get_already_homework(class_id):
     93     score_list = models.StudyRecord.objects.select_related().filter(student=class_id ).values_list( 'score' )#学习成绩
     94     number = 0
     95     for score in score_list:
     96         if score != (0,):  # (0,"N/A")
     97             number += 1  #通过 学习成绩 不等于0 计算#已交作业的数量
     98     return number
     99 #————#班级学生详情#计算#学员已交作业的数量————#
    100 
    101 #班级学生详情#学员已交作业的数量#作业查名字
    102 @login_required  # 登陆后页面才能访问
    103 @check_permission #权限控制
    104 def coursetop_homework(request,class_id):
    105     classes_obj = models.ClassList.objects.get(id=class_id)#通过ID获取02班级表
    106     class_grade_dic=get_course_grades(classes_obj.id)#{学员ID:分数}        #全班成绩
    107     ranking_dic=get_course_ranking(class_grade_dic)#{学员ID: [分数, 排名] } #全班排名
    108     enrollmentlist=classes_obj.enrollment_set.all()#通过班级ID,获取06学员报名信息表
    109 
    110     dict = {}#{1: 3, 4: 2,}#{学员ID: 数量}
    111     for item in enrollmentlist:
    112         d = get_already_homework( item.id )#根据06学员报名信息表#学员ID #计算#学员已交作业的数量
    113         dict[item.id]= d
    114 
    115     list = sorted(dict.items(),key=lambda x:x[1])#进行排序后的列表#以第2个参数对比
    116     #list[ (4, 2), (16, 2)]    #list[ (学员ID, 数量)]
    117 
    118     lists=[] #[{1: (19, 0)}, {2: (20, 0)}]#[{排名: (学员ID, 数量)}]
    119     for item in list:
    120         temp={}
    121         temp[list.index( item ) + 1] = item  # 循环添加 排名数 到 排序后的列表 #按已交作业数量少到多排序
    122         lists.append(temp)
    123     print('已交作业:',lists)
    124 
    125     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
    126     page = Page( request.GET.get( 'p', 1 ), len( lists ) )  # 当前页数 默认为1 #总数量
    127     lists = lists[page.start:page.end]  # 切片取当前页的数据
    128     page_str = page.page_str('/bpm/coursetop_homework/%s/'%(class_id)) # 总页数 传入url
    129     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
    130 
    131     return render(request,'bpm_coursetop/coursetop_homework.html',locals())
    132 # ————————66PerfectCRM实现CRM课程作业排名————————
    133 
    134 # ————————67PerfectCRM实现CRM课程出勤排名————————
    135 #————#班级学生详情#学员出勤次数 #出勤次数查名字————#
    136 #班级学生详情#计算#学员出勤次数
    137 def get_stu_attendance(enroll_obj_id):
    138     attendance_list=models.StudyRecord.objects.select_related().filter(student=enroll_obj_id).values_list('attendance')
    139     number=0
    140     for attendance in attendance_list:
    141         if attendance == (0,) :
    142             number += 1
    143     return number
    144 #————#班级学生详情#学员出勤次数 #出勤次数查名字————#
    145 
    146 #班级学生详情#学员出勤次数 #出勤次数查名字
    147 @login_required  # 登陆后页面才能访问
    148 @check_permission #权限控制
    149 def coursetop_attendance(request,class_id):
    150     classes_obj = models.ClassList.objects.get(id=class_id)#通过ID获取02班级表
    151     class_grade_dic=get_course_grades(classes_obj.id)#{学员ID:分数}        #全班成绩
    152     ranking_dic=get_course_ranking(class_grade_dic)#{学员ID: [分数, 排名] } #全班排名
    153     enrollmentlist=classes_obj.enrollment_set.all()#通过班级ID,获取06学员报名信息表
    154 
    155     dict = {} #{1: 3, 4: 2,}#{学员ID: 次数}
    156     for item in enrollmentlist:
    157         d = get_stu_attendance( item.id )#根据06学员报名信息表#学员ID #计算#学员学员出勤次数
    158         dict[item.id]= d # 循环添加 {学员ID: 次数} #排序后的字典
    159 
    160     list = sorted(dict.items(),key=lambda x:x[1])#进行排序后的列表#以第2个参数对比 #按出勤次数少到多排序
    161     #list[ (4, 2), (16, 2)]    #list[ (学员ID, 次数)]
    162 
    163     lists=[]#[{1: (19, 3)}, {2: (20, 1)}]#[{排名: (学员ID, 次数)}]
    164     for item in list:
    165         temp={}
    166         temp[list.index( item ) + 1] = item  # 循环添加 排名数 #排序后的列表
    167         lists.append(temp)
    168     print('全班出勤',lists)
    169 
    170     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
    171     page = Page( request.GET.get( 'p', 1 ), len( lists ) )  # 当前页数 默认为1 #总数量
    172     lists = lists[page.start:page.end]  # 切片取当前页的数据
    173     page_str = page.page_str('/bpm/coursetop_attendance/%s/'%(class_id)) # 总页数 传入url
    174     # ————————70PerfectCRM实现CRM业务流程(bpm)课程排行分页————————
    175 
    176     return render(request,'bpm_coursetop/coursetop_attendance.html',locals())
    177 # ————————67PerfectCRM实现CRM课程出勤排名————————
    # coursetop_views.py

      1 # kingadmin.py
      2 # ————————04PerfectCRM实现King_admin注册功能————————
      3 from crm import models
      4 #print("kingadmin crm",models.Customer)
      5 
      6 # ————————05PerfectCRM实现King_admin注册功能获取内存————————
      7 # from king_admin.base_admin import register,BaseAdmin
      8 from king_admin.base_admin import site,BaseAdmin
      9 # ————————05PerfectCRM实现King_admin注册功能获取内存————————
     10 
     11 # ————————24PerfectCRM实现King_admin自定义操作数据————————
     12 from django.shortcuts import render
     13 # ————————24PerfectCRM实现King_admin自定义操作数据————————
     14 
     15 # ————————28PerfectCRM实现King_admin编辑限制————————
     16 from django.forms import ValidationError
     17 from django.shortcuts import render,redirect
     18 # ————————28PerfectCRM实现King_admin编辑限制————————
     19 
     20 
     21 
     22 
     23 # ————————62PerfectCRM实现CRM讲师讲课记录————————
     24 # 02班级表
     25 class ClassListAdmin(BaseAdmin):
     26     list_display = ['id', 'branch', 'course', 'class_type', 'semester', 'start_date', 'end_date']  # 显示字段表头
     27     list_filter = ['branch', 'course', 'class_type']  # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
     28     filter_horizontal = ['teachers']  #复选框
     29 site.register(models.ClassList,ClassListAdmin)               #02班级表
     30 
     31 # ————————62PerfectCRM实现CRM讲师讲课记录————————
     32 
     33 
     34 
     35 
     36 #04客户信息表
     37 class CustomerAdmin(BaseAdmin):#定制Djanago admin
     38     # ————————54PerfectCRM实现CRM客户报名链接————————
     39     # list_display = ('id', 'qq', 'source', 'consultant', 'content', 'date')  # 显示字段表头
     40     list_display = ('id', 'qq', 'source', 'consultant', 'content', 'date','status','enroll')  # 显示字段表头
     41     # ————————54PerfectCRM实现CRM客户报名链接————————
     42     # ————————11PerfectCRM实现King_admin分页显示条数————————
     43     list_per_page = 2  #分页条数  # 默认分页条数10
     44     # ————————11PerfectCRM实现King_admin分页显示条数————————
     45     # ————————16PerfectCRM实现King_admin日期过滤————————
     46     # ————————15PerfectCRM实现King_admin多条件过滤————————
     47     # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
     48     # list_filter = ('source','consultant','consult_courses',)
     49     list_filter = ('date','source','consultant','consult_courses',)
     50     # ————————15PerfectCRM实现King_admin多条件过滤————————
     51     # ————————16PerfectCRM实现King_admin日期过滤————————
     52     # ————————18PerfectCRM实现King_admin搜索关键字————————
     53     #搜索(不能包含CharField)(注意加 逗号 , )
     54     search_fields = ('name','qq',)
     55     # ————————18PerfectCRM实现King_admin搜索关键字————————
     56     # ————————26PerfectCRM实现King_admin自定义排序————————
     57     ordering = '-qq'  #自定义排序,默认'-id'
     58     # ————————26PerfectCRM实现King_admin自定义排序————————
     59     # ————————27PerfectCRM实现King_admin编辑复选框————————
     60     filter_horizontal = ('tags',) #复选框
     61     # ————————27PerfectCRM实现King_admin编辑复选框————————
     62     # ————————33PerfectCRM实现King_admin编辑整张表限制————————
     63     readonly_table=True#默认表单不锁定
     64     # ————————33PerfectCRM实现King_admin编辑整张表限制————————
     65 
     66     # ————————55PerfectCRM实现CRM客户报名状态颜色变化————————
     67     colored_fields = {
     68         'status':{'已报名':"rgba(145, 255, 0, 0.78)",
     69                   '未报名':"#ddd"},}
     70     # ————————55PerfectCRM实现CRM客户报名状态颜色变化————————
     71 
     72     # ————————54PerfectCRM实现CRM客户报名链接————————
     73     def enroll(self):
     74         '''报名'''
     75         print("customize field enroll",self)
     76         link_name = "报名"
     77         if self.instance.status == 0:
     78             link_name = "报名新课程"
     79         return '''<a target="_blank" class="btn-link" href="/bpm/customer/%s/enrollment/">点击%s</a> ''' % (self.instance.id,link_name)
     80                 # url(r'^customer/(d+)/enrollment/$', sales_views.enrollment, name="enrollment"),  # 客户招生#报名流程一 下一步
     81                 # target属性用于表示所链接文件打开到的位置 #记住,“”内的文字只是表示一个对象的名子。
     82     enroll.display_name = "报名链接"
     83     # ————————54PerfectCRM实现CRM客户报名链接————————
     84 
     85 
     86 
     87     # ————————24PerfectCRM实现King_admin自定义操作数据————————
     88     # from django.shortcuts import render
     89     actions = ['test_actions',]#定制功能    #测试返回到一个新页面
     90     def test_actions(self,request,arg2):#对应的函数 #request类自己的请求  #arg2类的内容
     91         return render(request,"king_admin/table_index.html")
     92     test_actions.short_description = "测试显示中文"
     93     # ————————24PerfectCRM实现King_admin自定义操作数据————————
     94 
     95     # ————————28PerfectCRM实现King_admin编辑限制————————
     96     # ————————31PerfectCRM实现King_admin编辑多对多限制————————
     97     # readonly_fields = ('qq', 'consultant',)  # 不可修改
     98     readonly_fields = ('qq', 'consultant','tags',)  # 不可修改
     99     # ————————31PerfectCRM实现King_admin编辑多对多限制————————
    100 
    101     # ————————29PerfectCRM实现King_admin编辑自定义限制————————
    102     def default_form_validation(self,obj):
    103         print('validation:制定的',obj.cleaned_data)
    104         consult_course=obj.cleaned_data.get('content','')#自制验证字段
    105         if len(consult_course)<10:
    106             return ValidationError(#添加错误信息 返回
    107                                 ("该字段%(field)s 咨询内容记录不能少于10个字符"),
    108                                 code='invalid',
    109                                 params={'field':'content',},
    110                             )
    111     # ————————29PerfectCRM实现King_admin编辑自定义限制————————
    112 
    113     # ————————28PerfectCRM实现King_admin编辑限制————————
    114 
    115     # ————————30PerfectCRM实现King_admin编辑自定义字段验证————————
    116     def clean_name(self,obj,*args,**kwargs):#名称验证 单个
    117         name=obj.cleaned_data['name']
    118         if not name:
    119             obj.add_error('name','不能为空!')
    120             return ValidationError(#添加错误信息 返回
    121                                 ("%(field)s:该字段 不能为空"),
    122                                 code='invalid',
    123                                 params={'field':'name',},
    124                             )
    125         elif len(name)<5:
    126             obj.add_error('name','不能小于5个字符!')
    127             #return ValidationError('',)
    128             return ValidationError(#添加错误信息 返回
    129                                 ("%(field)s:该字段 不能小于5个字符!"),
    130                                 code='invalid',
    131                                 params={'field':'name',},
    132                             )
    133     # ————————30PerfectCRM实现King_admin编辑自定义字段验证————————
    134 
    135 # ————————34PerfectCRM实现CRM自定义用户————————
    136 #10账号表
    137 class UserProfileAdmin(BaseAdmin):#定制Djanago admin
    138     list_display = ('id', 'email', 'name')  # 显示字段表头
    139 
    140     # ————————36PerfectCRM实现King_admin密码修改————————
    141     readonly_fields = ('password',)   # 不可修改,限制
    142 
    143     # ————————72PerfectCRM实现CRM动态菜单和角色————————
    144     # filter_horizontal = ('user_permissions','groups') #复选框
    145     filter_horizontal = ('user_permissions', 'groups','roles')  # 复选框
    146     # ————————72PerfectCRM实现CRM动态菜单和角色————————
    147 
    148     modelform_exclude_fields=['last_login']#排除#不显示 #自增日期 #base_admin.py #forms.py
    149     # ————————36PerfectCRM实现King_admin密码修改————————
    150 
    151 site.register(models.UserProfile, UserProfileAdmin)
    152 # ————————34PerfectCRM实现CRM自定义用户————————
    153 
    154 # ————————05PerfectCRM实现King_admin注册功能获取内存————————
    155 # register(models.Customer,CustomerAdmin)
    156 # register(models.CourseRecord)
    157 site.register(models.Customer,CustomerAdmin)
    158 # ————————58PerfectCRM实现king_admin批量生成上课记录————————
    159 # site.register(models.CourseRecord)
    160 # ————————58PerfectCRM实现king_admin批量生成上课记录————————
    161 # ————————05PerfectCRM实现King_admin注册功能获取内存————————
    162 
    163 # ————————04PerfectCRM实现King_admin注册功能————————
    164 
    165 
    166 # ————————56PerfectCRM实现CRM客户报名缴费链接————————
    167 # 06学员报名信息表
    168 class EnrollmentAdmin(BaseAdmin):  # 定制Djanago admin
    169     list_display = ('id', 'customer', 'enrolled_class', 'consultant', 'Pay_cost', 'date', 'payment')  # 显示字段表头
    170 
    171     # ————————58PerfectCRM实现king_admin批量生成上课记录————————
    172     list_filter = ('enrolled_class','consultant', 'Pay_cost',) # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
    173     # ————————58PerfectCRM实现king_admin批量生成上课记录————————
    174 
    175     colored_fields = {
    176         'Pay_cost': {True: "rgba(145, 255, 0, 0.78)",
    177                      False: "#ddd"}, }
    178     def payment(self):
    179         link_name = "增加缴费"
    180         if self.instance.Pay_cost == False:
    181             link_name = "缴费"
    182         return '''<a target="_blank" class="btn-link"  href="/bpm/payment/%s/" >点击%s</a> ''' % (self.instance.id, link_name)
    183         # url(r'^payment/(d+)/$', financial_views.payment, name="payment"),  # 报名流程四    缴费   #财务
    184         # target属性用于表示所链接文件打开到的位置 #记住,“”内的文字只是表示一个对象的名子。
    185     payment.display_name = "缴费链接"
    186 site.register(models.Enrollment, EnrollmentAdmin)  # 06学员报名信息表
    187 # ————————56PerfectCRM实现CRM客户报名缴费链接————————
    188 
    189 # ————————58PerfectCRM实现king_admin批量生成上课记录————————
    190 # 07缴费记录表
    191 class PaymentAdmin(BaseAdmin):
    192     list_display = ['id', 'customer', 'course', 'amount', 'consultant','date']  # 显示字段表头
    193     list_filter = ('customer', 'course', 'consultant',)  # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
    194 
    195 from django.shortcuts import render, HttpResponse, redirect
    196 # 08每节课上课纪录表
    197 class CourseRecordAdmin(BaseAdmin):
    198     list_display = ['id', 'from_class', 'day_num', 'teacher', 'has_homework', 'homework_title', 'homework_content','outline', 'date']  # 显示字段表头
    199     list_filter = ('from_class', 'teacher', 'date')  # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
    200     def initialize_studyrecords(self, request, queryset):  # 制定功能
    201         print('initialize_studyrecords', self, request, queryset)
    202         if len(queryset) > 1:
    203             return HttpResponse("同时只能选择一个班级!")
    204         print('获取对应的学员', queryset[0].from_class.enrollment_set.all())  # _set反向查询
    205         new_obj_list = []  # 用于批量创建事务  #防止数据库事物回滚
    206         for enrll_obj in queryset[0].from_class.enrollment_set.all():  # 创建学习记录
    207             #     models.StudyRecord.objects.get_or_create(       #get_or_ #防止报错
    208             #         student=enrll_obj,#对应学员
    209             #         course_record=queryset[0],
    210             #         attendance=0,#签到状态,默认签到,
    211             #         score=0,#成绩
    212             #     )
    213 
    214             # 防止数据库事物回滚    #"""09学习纪录"""
    215             new_obj_list.append(models.StudyRecord(
    216                 student=enrll_obj,  # 对应学员
    217                 course_record=queryset[0],  # 班级#节课
    218                 attendance=0,  # 签到状态,默认签到,
    219                 score=0,  # 成绩
    220             ))
    221         try:
    222             models.StudyRecord.objects.bulk_create(new_obj_list)  # bulk_create批量创建数据库事物 #统一最后保存
    223         except Exception as e:
    224             return HttpResponse('批量创建失败,本节课可能有相应的上课记录')
    225 
    226         return redirect("/king_admin/crm/studyrecord/?course_record=%s" % queryset[0].id)  # 学习记录 #加上过滤
    227 
    228     actions = ['initialize_studyrecords', ]
    229     initialize_studyrecords.short_description = "创建班级本节上课记录"  # 显示别名
    230 # 09学习纪录
    231 class StudyRecordAdmin(BaseAdmin):
    232     list_display = ['id', 'student', 'course_record', 'attendance', 'score', 'date']  # 显示字段表头
    233 
    234     list_filter = ['course_record', 'attendance', 'score', 'student']  # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
    235 
    236     list_editable = ['score', 'attendance']  # 可编辑   #用于上课点名 批改成绩
    237 
    238 site.register(models.Payment, PaymentAdmin)  # 07缴费记录表
    239 site.register(models.CourseRecord, CourseRecordAdmin)  # 08每节课上课纪录表
    240 site.register(models.StudyRecord, StudyRecordAdmin)  # 09学习纪录
    241 # ————————58PerfectCRM实现king_admin批量生成上课记录————————
    242 
    243 
    244 # ————————72PerfectCRM实现CRM动态菜单和角色————————
    245 # 11角色表
    246 class RoleAdmin(BaseAdmin):
    247     list_display = ['id', 'name']  # 显示字段表头
    248     filter_horizontal = ['menus']  # 复选框
    249 site.register(models.Role,RoleAdmin) #11角色表
    250 
    251 # 13一层菜单名
    252 class FirstLayerMenuAdmin(BaseAdmin):
    253     list_display = ['id', 'name', 'url_type', 'url_name', 'order']  # 显示字段表头
    254 site.register(models.FirstLayerMenu,FirstLayerMenuAdmin)  #13一层菜单名
    255 # 14二层菜单名
    256 class SubMenuMenuAdmin(BaseAdmin):
    257     list_display = ['id', 'name', 'url_type', 'url_name', 'order']  # 显示字段表头
    258 site.register(models.SubMenu,SubMenuMenuAdmin)   #14二层菜单名
    259 # ————————72PerfectCRM实现CRM动态菜单和角色————————
    260 
    261 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
    262 class GroupsAdmin(BaseAdmin):
    263     list_display = ['id', 'name']  # 显示字段表头
    264     filter_horizontal = ['permissions']  # 复选框
    265 site.register(models.Groups,GroupsAdmin)   #14二层菜单名
    266 # ————————74PerfectCRM实现CRM权限和权限组限制访问URL————————
    # kingadmin.py


     

    如果感觉本章博客对您有帮助,请尽情打赏吧!

  • 相关阅读:
    扶桑号战列舰【单调栈+线段树】
    c++ vector基本函数、排序、查找用法
    路【邻接矩阵存图找最短路】
    free【分层图最短路】
    Magic Line【坐标点排序方法】
    Stones【中石油个人赛第十七场I】
    Second Large Rectangle【单调栈】
    点坐标求三角形面积【向量差乘】
    Random Point in Triangle【随机数解决期望值问题】
    JavaScript——基础知识,开始我们的js编程之旅吧!
  • 原文地址:https://www.cnblogs.com/ujq3/p/9084308.html
Copyright © 2011-2022 走看看