# student_urls.py
# ————————60PerfectCRM实现CRM学生上课记录————————
from django.conf.urls import url
from bpm.student import student_views urlpatterns = [
url(r'^student_course/$', student_views.student_course, name='student_course'), #学生报名的课程
url(r'^studyrecords/(\d+)/$', student_views.studyrecords, name='studyrecords'), # #学生上课记录列表StudyRecord # ————————61PerfectCRM实现CRM学生上传作业————————
url( r'^homework_detail/(\d+)/(\d+)/$', student_views.homework_detail, name='homework_detail' ), # 作业详情
# ————————61PerfectCRM实现CRM学生上传作业————————
]
# ————————60PerfectCRM实现CRM学生上课记录————————

# student_urls.py

 # student_views.py
# ————————60PerfectCRM实现CRM学生上课记录————————
from django.shortcuts import render #页面返回
from crm import models #数据库
from django.contrib.auth.decorators import login_required # 登陆后页面才能访问
#学生报名的课程
@login_required # 登陆后页面才能访问
def student_course(request):
enrollmentlist=request.user.stu_account.enrollment_set.all()#根据账号表关联的ID获取06学员报名信息表
return render(request, 'bpm_student/student_course.html', locals()) #学生上课记录列表
@login_required # 登陆后页面才能访问
def studyrecords(request,enroll_obj_id):
enroll_obj=models.Enrollment.objects.get(id=enroll_obj_id)#根据ID获取06学员报名信息表
studyrecordlist=enroll_obj.studyrecord_set.all()#根据06学员报名信息表的ID获取09学习纪录
return render(request,'bpm_student/studyrecords.html',locals()) # ————————60PerfectCRM实现CRM学生上课记录———————— # ————————61PerfectCRM实现CRM学生上传作业————————
from django.contrib.auth.decorators import login_required #登陆才能访问
from PerfectCRM import settings #静态配置文件 #作业上传 # 上传路径
import os,json,time #系统操作
from django.shortcuts import HttpResponse #页面返回
from django.shortcuts import redirect #页面返回
#作业详情
@login_required#登陆才能访问
def homework_detail(request,enroll_obj_id,studyrecord_id):
studyrecord_obj=models.StudyRecord.objects.get(id=studyrecord_id)#取学习记录 对象
enroll_obj=models.Enrollment.objects.get(id=enroll_obj_id)#取班级对象 # 作业根目录 班级ID 上课记录ID 学习记录ID
homework_path="{base_dir}/{class_id}/{course_record_id}/{studyercord_id}/".format(
base_dir=settings.HOMEWORK_DATA, #静态配置文件
class_id=studyrecord_obj.student.enrolled_class_id,#09学习纪录#学生名字#所报班级ID号
course_record_id=studyrecord_obj.course_record_id,#09学习纪录#每节课上课纪录表
studyercord_id=studyrecord_obj.id##09学习纪录
)
print('homework_path路径:',studyrecord_obj.student.enrolled_class_id,studyrecord_obj.course_record_id,studyrecord_obj.id) if os.path.exists(homework_path):#判断目录是否存在
file_lists = [] # 已经上传的文件列表
for file_name in os.listdir( homework_path ):
f_path = '%s/%s' % (homework_path, file_name) # 文件名字
modify_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.gmtime( os.stat( f_path ).st_mtime ) ) # 文件上传时间
file_lists.append( [file_name, os.stat( f_path ).st_size, modify_time] ) # 添加到文件列表#文件名字#文件大小文件上传时间 if request.method=="POST":#上传
ret=False
data=request.POST.get('data') #ajax
if data:#如果有删除动作
del_f_path="%s/%s"%(homework_path,data)#文件路径
print('删除文件,路径:',del_f_path)
os.remove(del_f_path) #删除
ret=True
return HttpResponse(json.dumps(ret))#ret=False
if request.is_ajax(): # ajax上传图片 #异步提交
print("POST",request.POST)
if not os.path.isdir( homework_path ): # 没有目录 #isdir返回true,如果路径名是指现有的目录。
os.makedirs( homework_path, exist_ok=True ) # 创建目录  
for k,v in request.FILES.items():#上传的文件
with open('%s/%s'%(homework_path,v.name),'wb') as f:#chunk 写入文件
for chunk in v.chunks(): #循环写文件
f.write(chunk)
return HttpResponse( json.dumps( {"status": 0, 'mag': "上传完成!", 'file_lists': file_lists} ) ) # 上传文件返回 if request.method=="POST":#上传
link = request.POST.get( 'link' ) # 让页面POST提交的值,在页面GET后仍然存在显示
if link:
homework_link=models.StudyRecord.objects.filter( id=studyrecord_id ).update(homework_link=link)
return redirect('/bpm/homework_detail/%s/%s/' %(enroll_obj_id,studyrecord_id) )#跳转到enrollment_rejection
return render(request,'bpm_student/homework_detail.html',locals())
# ————————61PerfectCRM实现CRM学生上传作业————————

# student_views.py

 # settings.py

 """
Django settings for PerfectCRM project. Generated by 'django-admin startproject' using Django 2.0.3. For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
""" import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'atkhzsd7emv4_okn@ynhji)p)qbpuvhq+a7@yx5=chaa0$l_br' # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles', # ————————04PerfectCRM实现King_admin注册功能————————
# 'crm.apps.CrmConfig',
'crm',
# ————————04PerfectCRM实现King_admin注册功能———————— # ————————02PerfectCRM创建ADMIN页面————————
'king_admin',
# ————————02PerfectCRM创建ADMIN页面————————
# ————————38PerfectCRM实现全局账号登录注销————————
'gbacc',
# ————————38PerfectCRM实现全局账号登录注销———————— # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
'bpm',
# ————————48PerfectCRM实现CRM客户报名流程学生合同———————— ] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ROOT_URLCONF = 'PerfectCRM.urls' TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# ————————02PerfectCRM创建ADMIN页面————————
'DIRS': [os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'king_admin/king_templates'), # ————————03PerfectCRM创建基本数据————————
os.path.join(BASE_DIR, 'DBadd/DBadd_templates'),
# ————————03PerfectCRM创建基本数据————————
# ————————38PerfectCRM实现全局账号登录注销————————
os.path.join(BASE_DIR, 'gbacc/gbacc_templates'),
# ————————38PerfectCRM实现全局账号登录注销———————— # ————————47PerfectCRM实现CRM客户报名流程————————
os.path.join(BASE_DIR, 'bpm/bpm_templates'), ]
# ————————47PerfectCRM实现CRM客户报名流程———————— ,
# ————————02PerfectCRM创建ADMIN页面————————
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
] WSGI_APPLICATION = 'PerfectCRM.wsgi.application' # Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
} # Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
] # Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/ # ————————01PerfectCRM基本配置ADMIN————————
#LANGUAGE_CODE = 'en-us' #英文转中文方法
LANGUAGE_CODE = 'zh-Hans'
# ————————01PerfectCRM基本配置ADMIN———————— TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' # ————————01PerfectCRM基本配置ADMIN————————
STATICFILES_DIRS = [os.path.join(BASE_DIR,'king_admin/static'),
# ————————01PerfectCRM基本配置ADMIN————————
# ————————38PerfectCRM实现全局账号登录注销————————
os.path.join(BASE_DIR, 'gbacc/static'),
# ————————38PerfectCRM实现全局账号登录注销———————— # ————————47PerfectCRM实现CRM客户报名流程————————
os.path.join(BASE_DIR, 'bpm/static'),]
# ————————47PerfectCRM实现CRM客户报名流程———————— # ————————34PerfectCRM实现CRM自定义用户————————
AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单
# ————————34PerfectCRM实现CRM自定义用户———————— # ————————44PerfectCRM实现账号快速注册登陆————————
# send e-mail
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' #email后端
EMAIL_USE_TLS = False #是否使用TLS安全传输协议
EMAIL_USE_SSL = True #是否使用SSL加密,qq企业邮箱要求使用
EMAIL_HOST = 'smtp.sina.cn' #发送邮件的邮箱 的 SMTP服务器 #根据情况重新配置
EMAIL_PORT = 465 #发件箱的SMTP服务器端口 #一般不需要修改465
EMAIL_HOST_USER = 'perfectcrm@sina.cn' #发送邮件的邮箱账号 #根据情况重新配置 #perfectcrm@sina.cn pydjango@sina.cn
EMAIL_HOST_PASSWORD = 'admin123456' #发送邮件的邮箱密码 #根据情况重新配置 # ————————44PerfectCRM实现账号快速注册登陆———————— # ————————46PerfectCRM实现登陆后页面才能访问————————
LOGIN_URL = '/gbacc/gbacc_login/'# login_url 配置 #默认 /accounts/login/ #注意: / (绝对路径)
# ————————46PerfectCRM实现登陆后页面才能访问———————— # ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片————————
ENROLLED_DATA='%s/bpm/static/enrolled_data'%BASE_DIR#证件上传 # 上传路径
# ————————51PerfectCRM实现CRM客户报名流程学生合同上传照片———————— # ————————61PerfectCRM实现CRM学生上传作业————————
HOMEWORK_DATA='%s/bpm/static/homeworks'%BASE_DIR #作业上传 # 上传路径
# ————————61PerfectCRM实现CRM学生上传作业————————

# settings.py

 #models.py

 # ————————01PerfectCRM基本配置ADMIN————————

 from django.db import models
# Create your models here. """
#运行 Terminal
# 生成 数据表
# python manage.py makemigrations
# 数据表 迁移
# python manage.py migrate
""" """01校区表"""
class Branch(models.Model):
name = models.CharField(max_length=128,unique=True) #校区名#CharField作用是保存文本,定长的变量类型
addr = models.CharField(max_length=128) #地址
def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return self.name #返回 #校区名
class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "01校区表" #verbose_name_plural给你的模型类起一个更可读的名字 """02班级表"""
class ClassList(models.Model):
#ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
branch = models.ForeignKey("Branch",on_delete=models.CASCADE)#校区 关联到 校区表
course = models.ForeignKey("Course",on_delete=models.CASCADE) #课程 关联到 课程表 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
contract = models.ForeignKey('ContractTemplate', blank=True, null=True, default=1,on_delete=models.CASCADE) # 合同表
# ————————48PerfectCRM实现CRM客户报名流程学生合同———————— class_type_choices = ( #上课形式
(0,'面授(脱产)'),
(1,'面授(周末)'),
(2,'网络班'),)
#PositiveSmallIntegerField正小整数 0 ~ 32767 #choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
class_type = models.SmallIntegerField(choices=class_type_choices)#上课形式 #PositiveSmallIntegerField正小整数 0 ~ 32767
semester = models.PositiveSmallIntegerField(verbose_name="学期") #课程的第几期 #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
teachers = models.ManyToManyField("UserProfile") # 老师 关联到 账号表 start_date = models.DateField(verbose_name="开班日期") #DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称 # DateField 日期格式 YYYY-MM-DD #verbose_name是Admin中显示的字段名称 #Django可空#数据库可以为空
end_date = models.DateField(verbose_name="结业日期",blank=True,null=True) def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return "%s %s %s" %(self.branch,self.course,self.semester) #返回 #%s格式化输出字符串 #校区#课程# 学期
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
unique_together=('branch','course','semester') #联合索引
verbose_name_plural = "02班级表" #verbose_name_plural给你的模型类起一个更可读的名字 """03课程表,可以报名那些课程"""
class Course(models.Model):
name = models.CharField(max_length=64,unique=True)#课程名 #CharField作用是保存文本,定长的变量类型
price = models.PositiveSmallIntegerField(verbose_name="学费")#学费#PositiveSmallIntegerField正小整数 0 ~ 32767
period = models.PositiveSmallIntegerField(verbose_name="周期(月)") #PositiveSmallIntegerField正小整数 0 ~ 32767
outline = models.TextField() #课程大纲 #文本类型
def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return self.name #返回 #课程名
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "03课程表"#verbose_name_plural给你的模型类起一个更可读的名字 '''04客户信息表'''
class Customer(models.Model):
name = models.CharField(max_length=32,blank=True,null=True)#客户名#CharField定长文本 #名字最长32 # Django可空 #数据库可以为空
qq = models.CharField(max_length=64,unique=True) #QQ号#CharField定长文本 #名字最长64 #唯一,不能重复
qq_name = models.CharField(max_length=64,blank=True,null=True)#QQ名 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空
phone = models.CharField(max_length=64,blank=True,null=True)#手机号 #CharField定长文本 #名字最长64 # Django可空 #数据库可以为空 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
id_num=models.CharField(max_length=64,blank=True,null=True,verbose_name='身份证号')#身份证号
email=models.EmailField(max_length=64,blank=True,null=True,verbose_name='邮箱')#email
sex_choices=((0,'保密'),(1,'男'),(2,'女'))
sex=models.SmallIntegerField(choices=sex_choices,default=0,verbose_name='性别')
# ————————48PerfectCRM实现CRM客户报名流程学生合同———————— # ————————53PerfectCRM实现CRM客户报名流程缴费————————
status_choices = ((0, '已报名'), (1, '未报名'), (2, '已退学'))
status = models.SmallIntegerField(choices=status_choices, default=1) # 学员状态
# ————————53PerfectCRM实现CRM客户报名流程缴费———————— source_choices = ( #客户渠道来源 (内存生成)
(0,'转介绍'),
(1,'QQ群'),
(2,'官网'),
(3,'百度推广'),
(4,'51CTO'),
(5,'知乎'),
(6,'市场推广'),)
#PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
source = models.SmallIntegerField(choices=source_choices)#客户渠道来源 #CharField定长文本#verbose_name是Admin中显示的字段名称#名字最长64 # Django可空 #数据库可以为空
referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True) #来自谁介绍的 #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
consult_courses = models.ForeignKey("Course",verbose_name="咨询课程", on_delete=models.CASCADE) #关联到 课程表 content= models.TextField(verbose_name="咨询详情") #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称 #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
tags = models.ManyToManyField("Tag",blank=True)#多对多关联到 标签表 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
consultant = models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到 账号表 memo = models.TextField(blank=True,null=True)#备注#TextField无限制长度的文本#Django可空#数据库可以为空 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return self.qq #返回 #QQ号 class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "04客户表" #verbose_name_plural给你的模型类起一个更可读的名字 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
#合同模版
class ContractTemplate(models.Model):
name=models.CharField('合同名称',max_length=64,unique=True)
template=models.TextField() def __str__(self):
return self.name
class Meta:
verbose_name_plural='合同表'
# ————————48PerfectCRM实现CRM客户报名流程学生合同———————— """05客户跟进表"""
class CustomerFollowUp(models.Model): #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
customer = models.ForeignKey("Customer", on_delete=models.CASCADE)#客户名 #关联到 客户信息表 content = models.TextField(verbose_name="跟进内容")#跟进的内容#TextField无限制长度的文本#verbose_name是Admin中显示的字段名称 #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
consultant =models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到 账号表 intention_choices =( #报名状态
(0,'2周内报名'),
(1,'1个月内报名'),
(2,'近期无报名计划'),
(3,'已在其它机构报名'),
(4,'已报名'),
(5,'已拉黑'),)
#PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
intention=models.SmallIntegerField(choices=intention_choices) #报名状态 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return "<%s:%s>" %(self.customer.qq,self.intention) #返回#格式化字符串#跨表里的QQ号#报名状态
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "05客户跟进表"#verbose_name_plural给你的模型类起一个更可读的名字 """06学员报名信息表"""
class Enrollment(models.Model):
# ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 #关联到 客户信息表
enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级",on_delete=models.CASCADE)#关联到 班级表
consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE) #关联到 账号表 # ————————52PerfectCRM实现CRM客户报名流程学生合同审核————————
contract_review = models.CharField(max_length=256, blank=True, null=True, verbose_name="合同审核") # 合同审核
# ————————52PerfectCRM实现CRM客户报名流程学生合同审核———————— #BooleanField布尔值类型#default=False默认(True)不允许出现空字符#verbose_name是Admin中显示的字段名称
contract_agreed = models.BooleanField(default=False,verbose_name="学员已经同意合同")#学员看合同
contract_approved = models.BooleanField(default=False,verbose_name="合同已经审核") #谁审核 # ————————53PerfectCRM实现CRM客户报名流程缴费————————
Pay_cost= models.BooleanField(default=False,verbose_name="缴费") #缴费状态#是不是交定金
# ————————53PerfectCRM实现CRM客户报名流程缴费———————— # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
# ————————57PerfectCRM实现admin批量生成上课记录————————
# return "%s %s" %(self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
return " 学员:%s |QQ: %s |班级:%s" %(self.customer.name,self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
# ————————57PerfectCRM实现admin批量生成上课记录————————
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
unique_together = ("customer","enrolled_class")#联合索引
verbose_name_plural = "06学员报名信息表"#verbose_name_plural给你的模型类起一个更可读的名字 """07缴费记录表"""
class Payment(models.Model):
#ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 关联到 客户信息表
course = models.ForeignKey("Course",verbose_name="所报课程",on_delete=models.CASCADE)#关联到 课程表 #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称#默认值=500
amount = models.PositiveIntegerField(verbose_name="数额",default=500)#缴费数额 #ForeignKey就是表与表之间的某种约定的关系#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
consultant = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#缴费给谁 关联到 账号表 #财务人员 #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
date=models.DateTimeField(auto_now_add=True)#创建时间(数据库自增) def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return "%s %s" %(self.customer,self.amount)#返回#格式化字符串#学员名字#缴费数额
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "07缴费记录表"#verbose_name_plural给你的模型类起一个更可读的名字 """08每节课上课纪录表"""
class CourseRecord(models.Model):
# ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
from_class = models.ForeignKey("ClassList",verbose_name="班级",on_delete=models.CASCADE) #那个班级 #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称
day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)") #第几节课 # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
teacher = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#老师是谁 关联到 账号表 #BooleanField布尔值类型#default=True默认(True)不允许出现空字符
has_homework = models.BooleanField(default=True) #有没有作业 # CharField定长文本#名字最长128#Django可空#数据库可以为空
homework_title = models.CharField(max_length=128,blank=True,null=True) #作业标题 #TextField无限制长度的文本#Django可空#数据库可以为空
homework_content = models.TextField(blank=True,null=True) #作业内容 #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
outline =models.TextField(verbose_name="本节课程大纲") #课程主要讲什么 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
date = models.DateField(auto_now_add=True)#创建时间(数据库自增) def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return " %s:%s" %(self.from_class,self.day_num)#返回#格式化字符串#班级#第几节(天)
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
unique_together = ("from_class","day_num") #联合索引
verbose_name_plural = "08每节课上课纪录表" #verbose_name_plural给你的模型类起一个更可读的名字 """09学习纪录"""
class StudyRecord(models.Model):
# ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
student = models.ForeignKey("Enrollment",on_delete=models.CASCADE)#学生名字 关联到 学员报名信息表
course_record = models.ForeignKey("CourseRecord",on_delete=models.CASCADE)#开课记录 # 关联到 每节课上课纪录表 attendance_choices = (# 本节课上课状态记录
(0,"已签到"),
(1,"迟到"),
(2,"缺勤"),
(3,"早退"),)
#PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
attendance = models.SmallIntegerField(choices=attendance_choices) # 本节课上课状态记录 # ————————61PerfectCRM实现CRM学生上传作业————————
homework_link = models.TextField(blank=True,null=True)#作业链接 #TextField无限制长度的文本#Django可空#数据库可以为空
# ————————61PerfectCRM实现CRM学生上传作业———————— score_choices = (#学习成绩
(100,"A+"),
(90,"A"),
(85,"B+"),
(80,"B"),
(75,"B-"),
(70,"C+"),
(65,"C"),
(40,"C-"),
(-20,"D"),
(-50,"COPY"),
(0,"N/A"),)
#PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
score = models.SmallIntegerField(choices=score_choices) #学习成绩 memo = models.TextField(blank=True,null=True)#TextField无限制长度的文本#Django可空#数据库可以为空 # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
date = models.DateField(auto_now_add=True)#创建时间(数据库自增) def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return "%s %s %s" % (self.student, self.course_record, self.score)#返回#格式化字符串#学生名字#开课记录#学习成绩
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
unique_together = ('student','course_record')#联合索引#学生名字#开课记录
verbose_name_plural = "09学习纪录"#verbose_name_plural给你的模型类起一个更可读的名字 # ————————34PerfectCRM实现CRM自定义用户————————
# """10账号表"""
# class UserProfile(models.Model):
# from django.contrib.auth.models import User # 使用django内置的用户表
#
# #OneToOneField一对一 #User是django Admin里的账号表#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
# user = models.OneToOneField(User,on_delete=models.CASCADE)# 用户名 #创建外键,关联django用户表
#
# name = models.CharField(max_length=32) #账号名(扩展用户字段)#CharField定长文本
#
# #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。#Django可空
# roles = models.ManyToManyField("Role",blank=True) #角色(权限) # 双向一对多==多对多
#
# def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
# return self.name #返回 #账号名
# class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
# verbose_name_plural = "10账号表"#verbose_name_plural给你的模型类起一个更可读的名字
# ————————34PerfectCRM实现CRM自定义用户———————— # ————————34PerfectCRM实现CRM自定义用户————————
#10账号表,创建用户和超级用户
from django.contrib.auth.models import BaseUserManager
class UserProfileManager(BaseUserManager):
def create_user(self, email, name, password=None):
"""
  创建并保存一个用户用给定的邮件,日期
  出生和密码。
"""
if not email:#没有email 报错
raise ValueError('用户必须有一个电子邮件地址') user = self.model(
email=self.normalize_email(email),#验证邮箱格式
name=name,
)
user.set_password(password)#加密
user.is_active = True
user.save(using=self._db)
return user
def create_superuser(self, email, name, password):
"""
  创建并保存一个超级用户具有给定邮件,日期
  出生和密码。
"""
user = self.create_user(email,
password=password,
name=name
)
user.is_active = True
user.is_superuser = True
user.save(using=self._db)
return user """10账号表"""
""" #删除数据库 #调用objects = UserProfileManager()#创建账号 #关联这个函数 #运行 Terminal
# 生成 数据表
# python manage.py makemigrations
# 数据表 迁移
# python manage.py migrate
Django Admin里账号密码重置方法
#运行 Terminal
python manage.py createsuperuser Email address: admin@qq.com
用户名 : admin
Password: admin123456
Password (again): admin123456
"""
from django.contrib.auth.models import AbstractBaseUser
# ————————35PerfectCRM实现CRM重写Admin密码修改————————
from django.utils.translation import ugettext_lazy as _ # 语言国际化
from django.utils.safestring import mark_safe
from django.contrib.auth.models import PermissionsMixin
# class UserProfile(AbstractBaseUser):
class UserProfile(AbstractBaseUser,PermissionsMixin):
# ————————35PerfectCRM实现CRM重写Admin密码修改————————
email=models.EmailField(
verbose_name='邮箱账号',
max_length=255,
unique=True#唯一 #登陆账号
)
name=models.CharField(max_length=32,verbose_name='用户名') # ————————35PerfectCRM实现CRM重写Admin密码修改————————
password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href=\"../password/\">修改密码</a>'''))
# ————————35PerfectCRM实现CRM重写Admin密码修改———————— is_active = models.BooleanField(default=True,verbose_name='合法账号')#权限#合法账号
is_superuser = models.BooleanField(default=False,verbose_name='超级账号') #超级账号
objects = UserProfileManager()#创建账号 #关联这个函数
USERNAME_FIELD ='email'#指定做为 #登陆账号
REQUIRED_FIELDS = ['name']#必填字段 # ————————60PerfectCRM实现CRM学生上课记录————————
stu_account = models.ForeignKey( "Customer", verbose_name='关联学员帐号', blank=True, null=True, on_delete=models.CASCADE,
help_text='报名成功后创建关联帐户' )
# ————————60PerfectCRM实现CRM学生上课记录———————— def get_full_name(self):
return self.email
def get_short_name(self):
#用户确认的电子邮件地址
return self.email
def __str__(self):
return self.name
def has_perm(self,perm,obj=None):
#指明用户是否被认为活跃的。以反选代替删除帐号。
#最简单的可能的答案:是的,总是
return True #有效 账号
def has_module_perms(self, app_label):
#指明用户是否可以登录到这个管理站点。
# 最简单的可能的答案:是的,总是
return True #职员状态
@property
def is_staff(self):
'''“用户的员工吗?”'''
#最简单的可能的答案:所有管理员都是员工
return self.is_superuser#是不是超级用户状态
# AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单 #settings.py
# ————————34PerfectCRM实现CRM自定义用户———————— """11角色表"""
class Role(models.Model):
name = models.CharField(unique=True,max_length=32)#角色名#CharField定长文本#角色名不可以重复#最长度=32字节
def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return self.name#返回 #角色名
class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "11角色表" #verbose_name_plural给你的模型类起一个更可读的名字 """12标签表"""
class Tag(models.Model):
name = models.CharField(max_length=64,unique=True) #标签名#CharField定长文本#最长度=64字节#不可以重复
def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
return self.name #返回 #标签名
class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
verbose_name_plural = "12标签表" #verbose_name_plural给你的模型类起一个更可读的名字 # ————————01PerfectCRM基本配置ADMIN————————

#models.py

 {#homework_detail.html#}
{## ————————61PerfectCRM实现CRM学生上传作业————————#}
{% extends 'bpm_master/bpm_sample.html' %}
{% block right-container-content %} {#自定义内容开始 右边页面内容#}
<div class="panel-default">
<div class="panel-body">
<h4>当前用户: {{ request.user }} | 学员名字:{{ request.user.stu_account.name }} |
学员QQ:{{ request.user.stu_account }}</h4>
<div class="row" style="margin-bottom: 20px">
<ol class="breadcrumb">
<li><a href="/bpm/my_course/">我的课程</a></li>
<li><a href="/bpm/studyrecords/{{ enroll_obj.id }}/">{{ enroll_obj.enrolled_class }}</a></li>
<li><a href="#">第:{{ studyrecord_obj.course_record.day_num }}节</a></li>
</ol>
</div>
<h4>作业标题:{{ studyrecord_obj.course_record.homework_title }}</h4>
<h4>作业详情:
<pre>{{ studyrecord_obj.course_record.homework_content }}</pre>
</h4>
<h4>老师评语:
<pre>{{ studyrecord_obj.memo }}</pre>
</h4>
<h4>本节成绩: {{ studyrecord_obj.score }} </h4>
<h4>本节作业链接:
<pre>{{ studyrecord_obj.homework_link }}</pre>
</h4>
<form method="post" class="form-horizontal" role="form">{% csrf_token %}
<input type="text" class="form-control" name="link" placeholder="作业链接">
<input type="submit" class="btn btn-info" value="提交">
</form> <hr>
<h4>已经上传的文件: <a id="refresh">刷新</a></h4>
<div class="row">
<div class="col-xs-9 col-md-6">
{% for file in file_lists %}
<div class="right">
{% for foo in file %}
<a>{{ foo }}</a> |
{% endfor %}
<span class="img_f hide">{{ file.0 }}</span>
<a class="del_img">删除</a>
</div>
<br>
{% endfor %}
</div>
</div>
<h4>请上传作业</h4>
<form action="{{ request.path }}" method="post" id="dropz" enctype="multipart/form-data"
class="form-group dropzone">{% csrf_token %}
<input type="hidden" name="file_id" ng-model="file_id" id="file_id"/>
</form>
<h4>课程大纲:
<pre>{{ studyrecord_obj.course_record.outline }}</pre>
</h4>
</div>
</div>
{% endblock %} {% block js %}
<script>
//页面加载时绑定按钮点击事件
$("#refresh").click(function () {
window.location.reload();//刷新当前页面.
}); $('.del_img').click(function () {
s = $(this);
texts = s.parent().children("span").text();
{# alert(texts);#}
$.ajax({
url: "{{ requset.path }}",
type: "post",
data: {"data": texts},
headers: {'X-CSRFtoken': $.cookie('csrftoken')},
success: function (arg) {
if (arg) {
alert('删除成功!');
s.parent('div').addClass('hide');
{# #添加样式#隐藏#}
}
}
})
}); Dropzone.autoDiscover = false;
appElement = document.querySelector('div .inmodal');
myDropzone = new Dropzone("#dropz", {
url: "{{ request.path }}",//文件提交地址
paramName: "file", //默认为file
method: "post", //也可用put
addRemoveLinks: true,
maxFiles: 1,//一次性上传的文件数量上限
maxFilesize: 2, //文件大小,单位:MB
acceptedFiles: ".zip,.7z", //上传的类型
{# uploadMultiple: true,#}//上传多个
parallelUploads: 1,//一次上传的文件数量
dictDefaultMessage: '请将作业压缩打包后上传',
dictMaxFilesExceeded: "您最多只能上传1个文件!",
dictResponseError: '文件上传失败!',
dictInvalidFileType: "文件类型只能是*.zip,*.7z。",
dictFallbackMessage: "浏览器不受支持",
dictFileTooBig: "文件过大上传文件最大支持.",
dictRemoveLinks: "删除",
dictCancelUpload: "取消", init: function () {
this.on("addedfile", function (file) {
//上传文件时触发的事件
document.querySelector('div .dz-default').style.display = 'none';
});
this.on("success", function (file, data) {
//上传成功触发的事件
console.log('ok');
});
this.on("error", function (file, data) {
//上传失败触发的事件
console.log('fail');
var message = '';
//lavarel框架有一个表单验证,
//对于ajax请求,JSON 响应会发送一个 422 HTTP 状态码,
//对应file.accepted的值是false,在这里捕捉表单验证的错误提示
if (file.accepted) {
$.each(data, function (key, val) {
message = message + val[0] + ';';
});
//控制器层面的错误提示,file.accepted = true的时候;
alert(message);
}
});
this.on("removedfile", function (file) {
//删除文件时触发的方法
document.querySelector('div .dz-default').style.display = 'block';
});
}
});
</script>
{% endblock %}
{## ————————61PerfectCRM实现CRM学生上传作业————————#}

{#homework_detail.html#}

 {#studyrecords.html#}
{## ————————60PerfectCRM实现CRM学生上课记录————————#}
{% extends 'bpm_master/bpm_sample.html' %}
{% load bpm_tags %}
{% block right-container-content %} {#自定义内容开始 右边页面内容#}
<div class="panel-default">
<div class="panel-body">
<h4>当前用户: {{ request.user }} | 学员名字:{{ request.user.stu_account.name }} |
学员QQ:{{ request.user.stu_account }}</h4>
<ol class="breadcrumb">
<li><a href="/bpm/student_course/">我的课程</a></li>
<li><a href="/bpm/studyrecords/{{ enroll_obj.id }}/">{{ enroll_obj.enrolled_class }}</a></li>
</ol> <table class="table table-striped table-responsive ">
<thead>
<tr>
<th>课程节次</th>
<th>签到状态</th>
<th>本节作业</th>
<th>本节成绩</th>
<th>本节讲师</th>
<th>上课日期</th>
<th>本节大纲</th>
<th>作业标题</th>
<th>作业要求</th>
</tr>
</thead> <tbody>
{% for studyrecord in studyrecordlist %}
<tr>
<td>{{ studyrecord.course_record.day_num }}</td>
{#课程节次#}
<td>{{ studyrecord.get_attendance_display }}</td>
{#签到状态#}
<td>
<a href="{% url 'homework_detail' enroll_obj.id studyrecord.id %}">
{{ studyrecord.course_record.has_homework }}
</a>
</td>
{#本节作业#}
<td>{{ studyrecord.get_score_display }}</td>
{#本节成绩#}
<td>{{ studyrecord.course_record.teacher }}</td>
{#本节讲师#}
<td>{{ studyrecord.course_record.date }}</td>
{#上课日期#}
<td>
<pre style="width: 240px;height: 60px">{{ studyrecord.course_record.outline }}</pre>
{#本节大纲#}
</td>
<td>
<pre style="width: 240px;height: 60px">{{ studyrecord.course_record.homework_title }}</pre>
{#作业标题#}
</td>
<td>
<pre style="width: 240px;height: 60px">{{ studyrecord.course_record.homework_content }}</pre>
{#作业要求#}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}
{## ————————60PerfectCRM实现CRM学生上课记录————————#}

{#studyrecords.html#}


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

Django项目:CRM(客户关系管理系统)--71--61PerfectCRM实现CRM学生上传作业的更多相关文章

  1. Django项目:CRM(客户关系管理系统)--84--74PerfectCRM实现CRM权限和权限组限制访问URL

    #models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...

  2. Django项目:CRM(客户关系管理系统)--85--75PerfectCRM实现CRM扩展权限

    # sales_urls.py # ————————47PerfectCRM实现CRM客户报名流程———————— from django.conf.urls import url from bpm. ...

  3. Django项目:CRM(客户关系管理系统)--82--72PerfectCRM实现CRM动态菜单和角色

    #models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...

  4. Django项目:CRM(客户关系管理系统)--81--71PerfectCRM实现CRM项目首页

    {#portal.html#} {## ————————46PerfectCRM实现登陆后页面才能访问————————#} {#{% extends 'king_admin/table_index.h ...

  5. Django项目:CRM(客户关系管理系统)--73--63PerfectCRM实现CRM讲师下载作业

    # teacher_urls.py # ————————62PerfectCRM实现CRM讲师讲课记录———————— from django.conf.urls import url from bp ...

  6. Django项目:CRM(客户关系管理系统)--79--69PerfectCRM实现CRM业务流程(bpm)学生讲师分页

    # student_views.py # ————————60PerfectCRM实现CRM学生上课记录———————— from django.shortcuts import render #页面 ...

  7. Django CRM客户关系管理系统

    CRM需求分析 随着信息化时代带来的科技创新,CRM客户关系管理系统带来的效益在已经成为很多企业提高竞争优势的一分部,CRM客户关系管理系统将企业管理和客户关系管理集成到统一的平台,其系统功能主要体现 ...

  8. Django项目:CRM(客户关系管理系统)--70--60PerfectCRM实现CRM学生上课记录

    #urls.py """PerfectCRM URL Configuration The `urlpatterns` list routes URLs to views. ...

  9. Django项目:CRM(客户关系管理系统)--74--64PerfectCRM实现CRM课程排名详情

    #urls.py """PerfectCRM URL Configuration The `urlpatterns` list routes URLs to views. ...

随机推荐

  1. P2528 [SHOI2001]排序工作量之新任务

    P2528 [SHOI2001]排序工作量之新任务 题目描述 假设我们将序列中第i件物品的参数定义为Ai,那么排序就是指将A1,…,An从小到大排序.若i<j且Ai>Aj,则<i ...

  2. 汽车超人CEO郑超:不惧资本寒冬 融资已增至57亿

    汽车超人CEO郑超:不惧资本寒冬 融资已增至57亿 来源:互联网 时间:2017-06-01 阅读:3次     篇一 : 汽车超人CEO郑超:不惧资本寒冬 融资已增至57亿 近日记者获悉,金固股份旗 ...

  3. POJ-1976-A Mini Locomotive-dp

    A train has a locomotive that pulls the train with its many passenger coaches. If the locomotive bre ...

  4. PAT甲级——A1133 Splitting A Linked List【25】

    Given a singly linked list, you are supposed to rearrange its elements so that all the negative valu ...

  5. Django杂篇(2)

    目录 Django杂篇(2) cookie与session cookie session django中间件 自定义中间件 跨站请求伪造(csrf) CSRF的解决方案 Django杂篇(2) 本文主 ...

  6. Activiti添加批注(comment)信息

    在每次提交任务的时候需要描述一些批注信息,例如:请假流程提交的时候要描述信息为什么请假,如果领导驳回可以批注驳回原因等 1.添加批注 // 由于流程用户上下文对象是线程独立的,所以要在需要的位置设置, ...

  7. iOS开发系列-网络状态监控

    概述 在网络应用中,需要对用户设别的网络状态进行实时监控,可以让用户了解自己的网络状态出现网络问题提示用户. 一般在网络状态不好的场景下需要做一些处理比如: WIFT/3G/4G网络:自动下载高清图. ...

  8. curl http_code 状态码

    1.只得到一个url的http_code的状态码 curl -I -m 10 -o /dev/null -s -w %{http_code} http://127.0.0.1/a.html 查询hea ...

  9. 跟我一起使用create-react-app脚手架搭建vw-layout解决方案

    之前也是看过大漠的vw适配Vue-cli,我自己写H5,还有使用vue做项目的时候,会搭建大漠博客中的那一套. 现在在github上面,看见了一位博主使用create-react-app也是用vw适配 ...

  10. 在python2中的编码

    在python2中的编码 #_author:star#date:2019/10/29'''字符编码:ASCII:只能存英文和拉丁字符,gb2312:只能6700中文,1980年gbk1.0:存了200 ...