Django项目:CRM(客户关系管理系统)--73--63PerfectCRM实现CRM讲师下载作业
1 # teacher_urls.py 2 # ————————62PerfectCRM实现CRM讲师讲课记录———————— 3 from django.conf.urls import url 4 from bpm.teacher import teacher_views 5 urlpatterns = [ 6 url(r'^teacher_class/$', teacher_views.teacher_class,name='teacher_class'),#讲师班级 7 url(r'^teacher_class_detail/(\d+)/$', teacher_views.teacher_class_detail, name='teacher_class_detail'), # 讲师班级课节详情 8 9 # ————————63PerfectCRM实现CRM讲师下载作业———————— 10 url( r'^teacher_lesson_detail/(\d+)/(\d+)/$', teacher_views.teacher_lesson_detail,name='teacher_lesson_detail' ), # 本节课的学员 11 url( r'^homeworks/(\d+)/(\d+)/(\d+)/$', teacher_views.howk_down, name='howk_down' ), # 作业下载 12 # ————————63PerfectCRM实现CRM讲师下载作业———————— 13 ] 14 15 # ————————62PerfectCRM实现CRM讲师讲课记录————————
1 # teacher_views.py 2 # ————————62PerfectCRM实现CRM讲师讲课记录———————— 3 from django.contrib.auth.decorators import login_required # 登陆后页面才能访问 4 from django.shortcuts import render #页面返回 5 # 讲师班级 6 @login_required # 登陆后页面才能访问 7 def teacher_class(request): 8 # user_id=request.user.id #当前登陆的ID 9 # classlist=models.UserProfile.objects.get(id=user_id).classlist_set.all()#讲师所教班级 10 classes_obj = request.user.classlist_set.all() # 根据 登陆的ID 获取02班级表 11 return render( request, 'bpm_teacher/teacher_class.html', locals() ) 12 13 # 讲师班级课节详情 14 @login_required # 登陆后页面才能访问 15 def teacher_class_detail(request, class_id): 16 # user_id=request.user.id #当前登陆的ID 17 # classes_obj=models.UserProfile.objects.get(id=user_id).classlist_set.get(id=class_id)#所选的班级 18 classes_obj = request.user.classlist_set.get( id=class_id ) # 根据 登陆的ID 获取02班级表 19 courserecordlist = classes_obj.courserecord_set.all() # 根据 02班级表的ID 获取09学习纪录 20 return render( request, 'bpm_teacher/teacher_classes_detail.html', locals() ) 21 # ————————62PerfectCRM实现CRM讲师讲课记录———————— 22 23 # ————————63PerfectCRM实现CRM讲师下载作业———————— 24 from PerfectCRM import settings # 系统配置 25 import os # 系统操作 26 # 本节课的学员 27 @login_required # 登陆后页面才能访问 28 def teacher_lesson_detail(request, class_id, courserecord_id): 29 # classes_obj=models.UserProfile.objects.get(id=request.user.id).classlist_set.get(id=class_id)#所选的班级 30 classes_obj = request.user.classlist_set.get( id=class_id ) # 根据 登陆的ID 获取02班级表 31 courserecordlist = classes_obj.courserecord_set.get( id=courserecord_id ) # 根据 前端的ID 获取08每节课上课纪录表 32 33 # studyrecord_list=models.CourseRecord.objects.get(id=courserecord_id).studyrecord_set.all()#取本节课所有学员 34 studyrecord_list = courserecordlist.studyrecord_set.all() # 根据08每节课上课纪录表 #获取09学习纪录 #取本节课所有学员 35 36 for i in studyrecord_list: # 循环本节课所有学员 交作业的状态 37 studyrecord_id = i.id # 获取本节课所有学员的ID 38 if studyrecord_id: # 有获取到ID 39 HOMEWORK_path = '%s/%s/%s/%s/' % (settings.HOMEWORK_DATA, class_id, courserecord_id, studyrecord_id) # 作业目录 40 if os.path.exists( HOMEWORK_path ): # 判断目录是否存在 41 try:#防止后台误删文件 42 file_list = os.listdir( HOMEWORK_path ) # 取目录 下的文件 43 isfile = os.path.isfile( '%s%s' % (HOMEWORK_path, file_list[0]) ) # 判断是不是文件 44 studyrecord_list.filter( id=studyrecord_id ).update( delivery=isfile ) # 更新交付作业状态 45 except: 46 studyrecord_list.filter( id=studyrecord_id ).update( delivery=False ) # file_list 出错# 更新交付作业状态 47 else: 48 studyrecord_list.filter( id=studyrecord_id ).update( delivery=False )# 更新交付作业状态 49 return render( request, 'bpm_teacher/teacher_lesson_detail.html', locals() ) 50 51 from django.http import StreamingHttpResponse #页面返回 52 from crm import models #数据库 53 from django.shortcuts import redirect #页面返回 54 # 学员作业下载 55 @login_required # 登陆后页面才能访问 56 def howk_down(request, class_id, courserecord_id, studyrecord_id): 57 HOMEWORK_path = '%s/%s/%s/%s/' % (settings.HOMEWORK_DATA, class_id, courserecord_id, studyrecord_id) # 作业目录 58 print( '下载作业目录:', HOMEWORK_path ) 59 60 def file_iterator(file_path, chunk_size=512): # 获取文件 #chunk_size每次读取的大小 #文件迭代器 61 with open( file_path, 'rb', ) as f: # 循环打开 文件#以二进制读模式打开 62 while True: # 如果有文件 63 byte = f.read( chunk_size ) # read读最多大小字节,作为字节返回。#获取文件大小 64 if byte: 65 yield byte # 返回 yield 后的值作为第一次迭代的返回值. 循环下一次,再返回,直到没有可以返回的。 66 else: 67 break # 没有字节就中止 68 69 if os.path.exists( HOMEWORK_path ): # 判断目录是否存在 70 try:#防止后台误删文件 71 file_list = os.listdir( HOMEWORK_path ) # 取目录 下的文件 72 print( '文件名:', file_list, type( file_list ) ) 73 file_path = '%s%s' % (HOMEWORK_path, file_list[0]) # 下载文件路径 74 print( '下载文件路径:', file_path ) 75 response = StreamingHttpResponse( file_iterator( file_path ) ) # StreamingHttpResponse是将文件内容进行流式传输 76 response['Content-Type'] = 'application/octet-stream' # 文件类型 #应用程序/octet-stream.*( 二进制流,不知道下载文件类型) 77 file_name = 'attachment;filename=%s' % file_list[0] # 文件名字# 支持中文 78 response['Content-Disposition'] = file_name.encode() # 支持中文#编码默认encoding='utf-8' 79 return response # 返回下载 请求的内容 80 except: 81 models.StudyRecord.objects.get( id=studyrecord_id ).update( delivery=False ) # 更新交付作业状态 # file_list 出错 82 return redirect( '/bpm/teacher_lesson_detail/%s/%s/' % (class_id, courserecord_id) ) # 返回##本节课的学员 83 # ————————63PerfectCRM实现CRM讲师下载作业————————
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 # ————————35PerfectCRM实现CRM重写Admin密码修改———————— 390 password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href=\"../password/\">修改密码</a>''')) 391 # ————————35PerfectCRM实现CRM重写Admin密码修改———————— 392 393 is_active = models.BooleanField(default=True,verbose_name='合法账号')#权限#合法账号 394 is_superuser = models.BooleanField(default=False,verbose_name='超级账号') #超级账号 395 objects = UserProfileManager()#创建账号 #关联这个函数 396 USERNAME_FIELD ='email'#指定做为 #登陆账号 397 REQUIRED_FIELDS = ['name']#必填字段 398 399 400 # ————————60PerfectCRM实现CRM学生上课记录———————— 401 stu_account = models.ForeignKey( "Customer", verbose_name='关联学员帐号', blank=True, null=True, on_delete=models.CASCADE, 402 help_text='报名成功后创建关联帐户' ) 403 # ————————60PerfectCRM实现CRM学生上课记录———————— 404 405 def get_full_name(self): 406 return self.email 407 def get_short_name(self): 408 #用户确认的电子邮件地址 409 return self.email 410 def __str__(self): 411 return self.name 412 def has_perm(self,perm,obj=None): 413 #指明用户是否被认为活跃的。以反选代替删除帐号。 414 #最简单的可能的答案:是的,总是 415 return True #有效 账号 416 def has_module_perms(self, app_label): 417 #指明用户是否可以登录到这个管理站点。 418 # 最简单的可能的答案:是的,总是 419 return True #职员状态 420 @property 421 def is_staff(self): 422 '''“用户的员工吗?”''' 423 #最简单的可能的答案:所有管理员都是员工 424 return self.is_superuser#是不是超级用户状态 425 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单 #settings.py 426 # ————————34PerfectCRM实现CRM自定义用户———————— 427 428 """11角色表""" 429 class Role(models.Model): 430 name = models.CharField(unique=True,max_length=32)#角色名#CharField定长文本#角色名不可以重复#最长度=32字节 431 def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 432 return self.name#返回 #角色名 433 class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据 434 verbose_name_plural = "11角色表" #verbose_name_plural给你的模型类起一个更可读的名字 435 436 """12标签表""" 437 class Tag(models.Model): 438 name = models.CharField(max_length=64,unique=True) #标签名#CharField定长文本#最长度=64字节#不可以重复 439 def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。 440 return self.name #返回 #标签名 441 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据 442 verbose_name_plural = "12标签表" #verbose_name_plural给你的模型类起一个更可读的名字 443 444 # ————————01PerfectCRM基本配置ADMIN————————
1 {#teacher_lesson_detail.html#} 2 {## ————————63PerfectCRM实现CRM讲师下载作业————————#} 3 {% extends 'bpm_master/bpm_sample.html' %} 4 {% block right-container-content %} {#自定义内容开始 右边页面内容#} 5 <div class="panel-default"> 6 <div class="panel-default"> 7 <div class="panel-body"> 8 <h4>当前用户: {{ request.user }} | 讲师名字:{{ request.user.stu_account.name }} | 9 讲师QQ:{{ request.user.stu_account }} </h4> 10 <ol class="breadcrumb"> 11 <li><a href="/bpm/teacher_class/">我的班级</a></li> 12 <li><a href="{% url 'teacher_class_detail' classes_obj.id %}">{{ classes_obj }}</a></li> 13 <li> 14 <a href="{% url 'teacher_lesson_detail' classes_obj.id courserecordlist.id %}">第{{ courserecordlist.day_num }}节</a> 15 </li> 16 </ol> 17 <li> 18 <a target="_blank" 19 href="/king_admin/crm/courserecord/{{ courserecordlist.id }}/change/">作业标题:</a> 20 <pre>{{ courserecordlist.homework_title }}</pre> 21 </li> 22 <li> 23 <a target="_blank" 24 href="/king_admin/crm/courserecord/{{ courserecordlist.id }}/change/">作业要求:</a> 25 <pre>{{ courserecordlist.homework_content }}</pre> 26 </li> 27 28 29 <table class="table table-striped table-responsive"> 30 <thead> 31 <tr> 32 <th>学员ID</th> 33 <th>学员姓名</th> 34 <th> 35 <a target="_blank" href="/king_admin/crm/studyrecord/?course_record={{ courserecord_id }} ">签到状态</a> 36 </th> 37 <th> 作业链接</th> 38 <th> 39 {% if courserecordlist.has_homework %} 40 <a href="{% url 'teacher_lesson_detail' classes_obj.id courserecordlist.id %}">学员作业(多刷) </a> 41 {% else %} 42 <a style="color: #ff1900" target="_blank" 43 href="/king_admin/crm/courserecord/{{ courserecordlist.id }}/change/">创建新作业</a> 44 {% endif %} 45 </th> 46 <th> 47 {% if courserecordlist.has_homework %} 48 <a href="{% url 'teacher_lesson_detail' classes_obj.id courserecordlist.id %}">批改作业 </a> 49 {% else %} 50 没有作业 51 {% endif %} 52 </th> 53 </tr> 54 </thead> 55 56 57 <tbody> 58 {% for studyrecrd in studyrecord_list %} 59 <tr> 60 <td>{{ studyrecrd.student.id }}</td> 61 {#学员ID#} 62 <td>{{ studyrecrd.student.customer.name }}</td> 63 {#学员姓名#} 64 <td>{{ studyrecrd.get_attendance_display }}</td> 65 {#签到状态#} 66 <td> 67 <pre style="width: 240px;height: 60px">{{ studyrecrd.homework_link }}</pre> 68 </td> 69 {#作业链接#} 70 <td> 71 {% if studyrecrd.delivery %} 72 <a href="{% url 'howk_down' classes_obj.id studyrecrd.course_record_id studyrecrd.id %}">下载作业</a> 73 {% endif %}{#学员作业#} 74 </td> 75 <td> 76 {% if studyrecrd.course_record.has_homework %} 77 {% if studyrecrd.score == 0 %} 78 <a target="_blank" 79 href="/king_admin/crm/studyrecord/{{ studyrecrd.id }}/change/" 80 style="color: #ff1600">未批改</a> 81 {% else %} 82 <a target="_blank" 83 href="/king_admin/crm/studyrecord/{{ studyrecrd.id }}/change/" 84 style="color: #0014ff">{{ studyrecrd.get_score_display }}</a> 85 {% endif %} 86 {% endif %}{#批改作业#} 87 </td> 88 </tr> 89 {% endfor %} 90 </tbody> 91 </table> 92 </div> 93 </div> 94 </div> 95 {% endblock %} 96 {## ————————63PerfectCRM实现CRM讲师下载作业————————#}
1 {#teacher_classes_detail.html#} 2 {## ————————62PerfectCRM实现CRM讲师讲课记录————————#} 3 {% extends 'bpm_master/bpm_sample.html' %} 4 {% block right-container-content %} {#自定义内容开始 右边页面内容#} 5 <div class="panel-default"> 6 <div class="panel-default"> 7 <div class="panel-body"> 8 <h4>当前用户: {{ request.user }} | 讲师名字:{{ request.user.stu_account.name }} | 9 讲师QQ:{{ request.user.stu_account }} </h4> 10 <ol class="breadcrumb"> 11 <li><a href="/bpm/teacher_class/">我的班级</a></li> 12 <li><a href="{% url 'teacher_class_detail' classes_obj.id %}">{{ classes_obj }}</a></li> 13 </ol> 14 <table class="table table-striped table-responsive "> 15 <thead> 16 <tr> 17 <th><a target="_blank" href="/king_admin/crm/courserecord/add/">课程节次</a></th> 18 <th>签到状态</th> 19 <th>本节作业</th> 20 <th>上课日期</th> 21 <th>本节大纲</th> 22 <th>作业标题</th> 23 <th>作业要求</th> 24 </tr> 25 </thead> 26 27 28 <tbody> 29 {% for courserecord in courserecordlist %} 30 <tr> 31 <td><a target="_blank" 32 href="/king_admin/crm/courserecord/{{ courserecord.id }}/change/">第 {{ courserecord.day_num }}节</a> 33 </td> 34 {#课程节次#} 35 <td> 36 <a target="_blank" 37 href="/king_admin/crm/studyrecord/?course_record={{ courserecord.id }} ">点名/成绩</a> 38 </td> 39 {#签到状态#} 40 <td> 41 {## ————————63PerfectCRM实现CRM讲师下载作业————————#} 42 <a href="{% url 'teacher_lesson_detail' class_id courserecord.id %}"> 43 {## ————————63PerfectCRM实现CRM讲师下载作业————————#} 44 {{ courserecord.has_homework }} 45 </a> 46 </td> 47 {#本节作业#} 48 <td> {{ courserecord.date }}</td> 49 {#上课日期#} 50 <td> 51 <pre style="width: 240px;height: 60px">{{ courserecord.outline }} </pre> 52 </td> 53 {#本节大纲#} 54 <td> 55 <pre style="width: 240px;height: 60px">{{ courserecord.homework_title }}</pre> 56 </td> 57 {#作业标题#} 58 <td> 59 <pre style="width: 240px;height: 60px">{{ courserecord.homework_content }} </pre> 60 </td> 61 {#作业要求#} 62 </tr> 63 {% endfor %} 64 </tbody> 65 </table> 66 </div> 67 </div> 68 </div> 69 {% endblock %} 70 {## ————————62PerfectCRM实现CRM讲师讲课记录————————#}
如果感觉本章博客对您有帮助,请尽情打赏吧!
您的资助是我最大的动力!
金额随意,欢迎来赏!
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的
因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【颜言】!