1 # student_urls.py 2 # ————————60PerfectCRM實現CRM學生上課記錄———————— 3 from django.conf.urls import url 4 from bpm.student import student_views 5 6 urlpatterns = [ 7 url(r'^student_course/$', student_views.student_course, name='student_course'), #學生報名的課程 8 url(r'^studyrecords/(\d+)/$', student_views.studyrecords, name='studyrecords'), # #學生上課記錄列表StudyRecord 9 10 # ————————61PerfectCRM實現CRM學生上傳做業———————— 11 url( r'^homework_detail/(\d+)/(\d+)/$', student_views.homework_detail, name='homework_detail' ), # 做業詳情 12 # ————————61PerfectCRM實現CRM學生上傳做業———————— 13 ] 14 # ————————60PerfectCRM實現CRM學生上課記錄————————
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 @login_required # 登錄後頁面才能訪問 8 def student_course(request): 9 enrollmentlist=request.user.stu_account.enrollment_set.all()#根據帳號表關聯的ID獲取06學員報名信息表 10 return render(request, 'bpm_student/student_course.html', locals()) 11 12 #學生上課記錄列表 13 @login_required # 登錄後頁面才能訪問 14 def studyrecords(request,enroll_obj_id): 15 enroll_obj=models.Enrollment.objects.get(id=enroll_obj_id)#根據ID獲取06學員報名信息表 16 studyrecordlist=enroll_obj.studyrecord_set.all()#根據06學員報名信息表的ID獲取09學習紀錄 17 return render(request,'bpm_student/studyrecords.html',locals()) 18 19 # ————————60PerfectCRM實現CRM學生上課記錄———————— 20 21 # ————————61PerfectCRM實現CRM學生上傳做業———————— 22 from django.contrib.auth.decorators import login_required #登錄才能訪問 23 from PerfectCRM import settings #靜態配置文件 #做業上傳 # 上傳路徑 24 import os,json,time #系統操做 25 from django.shortcuts import HttpResponse #頁面返回 26 from django.shortcuts import redirect #頁面返回 27 #做業詳情 28 @login_required#登錄才能訪問 29 def homework_detail(request,enroll_obj_id,studyrecord_id): 30 studyrecord_obj=models.StudyRecord.objects.get(id=studyrecord_id)#取學習記錄 對象 31 enroll_obj=models.Enrollment.objects.get(id=enroll_obj_id)#取班級對象 32 33 # 做業根目錄 班級ID 上課記錄ID 學習記錄ID 34 homework_path="{base_dir}/{class_id}/{course_record_id}/{studyercord_id}/".format( 35 base_dir=settings.HOMEWORK_DATA, #靜態配置文件 36 class_id=studyrecord_obj.student.enrolled_class_id,#09學習紀錄#學生名字#所報班級ID號 37 course_record_id=studyrecord_obj.course_record_id,#09學習紀錄#每節課上課紀錄表 38 studyercord_id=studyrecord_obj.id##09學習紀錄 39 ) 40 print('homework_path路徑:',studyrecord_obj.student.enrolled_class_id,studyrecord_obj.course_record_id,studyrecord_obj.id) 41 42 if os.path.exists(homework_path):#判斷目錄是否存在 43 file_lists = [] # 已經上傳的文件列表 44 for file_name in os.listdir( homework_path ): 45 f_path = '%s/%s' % (homework_path, file_name) # 文件名字 46 modify_time = time.strftime( "%Y-%m-%d %H:%M:%S", time.gmtime( os.stat( f_path ).st_mtime ) ) # 文件上傳時間 47 file_lists.append( [file_name, os.stat( f_path ).st_size, modify_time] ) # 添加到文件列表#文件名字#文件大小文件上傳時間 48 49 50 if request.method=="POST":#上傳 51 ret=False 52 data=request.POST.get('data') #ajax 53 if data:#若是有刪除動做 54 del_f_path="%s/%s"%(homework_path,data)#文件路徑 55 print('刪除文件,路徑:',del_f_path) 56 os.remove(del_f_path) #刪除 57 ret=True 58 return HttpResponse(json.dumps(ret))#ret=False 59 if request.is_ajax(): # ajax上傳圖片 #異步提交 60 print("POST",request.POST) 61 if not os.path.isdir( homework_path ): # 沒有目錄 #isdir返回true,若是路徑名是指現有的目錄。 62 os.makedirs( homework_path, exist_ok=True ) # 建立目錄 63 for k,v in request.FILES.items():#上傳的文件 64 with open('%s/%s'%(homework_path,v.name),'wb') as f:#chunk 寫入文件 65 for chunk in v.chunks(): #循環寫文件 66 f.write(chunk) 67 return HttpResponse( json.dumps( {"status": 0, 'mag': "上傳完成!", 'file_lists': file_lists} ) ) # 上傳文件返回 68 69 if request.method=="POST":#上傳 70 link = request.POST.get( 'link' ) # 讓頁面POST提交的值,在頁面GET後仍然存在顯示 71 if link: 72 homework_link=models.StudyRecord.objects.filter( id=studyrecord_id ).update(homework_link=link) 73 return redirect('/bpm/homework_detail/%s/%s/' %(enroll_obj_id,studyrecord_id) )#跳轉到enrollment_rejection 74 return render(request,'bpm_student/homework_detail.html',locals()) 75 # ————————61PerfectCRM實現CRM學生上傳做業————————
1 # settings.py 2 3 """ 4 Django settings for PerfectCRM project. 5 6 Generated by 'django-admin startproject' using Django 2.0.3. 7 8 For more information on this file, see 9 https://docs.djangoproject.com/en/2.0/topics/settings/ 10 11 For the full list of settings and their values, see 12 https://docs.djangoproject.com/en/2.0/ref/settings/ 13 """ 14 15 import os 16 17 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 18 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 19 20 21 # Quick-start development settings - unsuitable for production 22 # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ 23 24 # SECURITY WARNING: keep the secret key used in production secret! 25 SECRET_KEY = 'atkhzsd7emv4_okn@ynhji)p)qbpuvhq+a7@yx5=chaa0$l_br' 26 27 # SECURITY WARNING: don't run with debug turned on in production! 28 DEBUG = True 29 30 ALLOWED_HOSTS = [] 31 32 33 # Application definition 34 35 INSTALLED_APPS = [ 36 'django.contrib.admin', 37 'django.contrib.auth', 38 'django.contrib.contenttypes', 39 'django.contrib.sessions', 40 'django.contrib.messages', 41 'django.contrib.staticfiles', 42 43 # ————————04PerfectCRM實現King_admin註冊功能———————— 44 # 'crm.apps.CrmConfig', 45 'crm', 46 # ————————04PerfectCRM實現King_admin註冊功能———————— 47 48 # ————————02PerfectCRM建立ADMIN頁面———————— 49 'king_admin', 50 # ————————02PerfectCRM建立ADMIN頁面———————— 51 # ————————38PerfectCRM實現全局帳號登陸註銷———————— 52 'gbacc', 53 # ————————38PerfectCRM實現全局帳號登陸註銷———————— 54 55 # ————————48PerfectCRM實現CRM客戶報名流程學生合同———————— 56 'bpm', 57 # ————————48PerfectCRM實現CRM客戶報名流程學生合同———————— 58 59 ] 60 61 MIDDLEWARE = [ 62 'django.middleware.security.SecurityMiddleware', 63 'django.contrib.sessions.middleware.SessionMiddleware', 64 'django.middleware.common.CommonMiddleware', 65 'django.middleware.csrf.CsrfViewMiddleware', 66 'django.contrib.auth.middleware.AuthenticationMiddleware', 67 'django.contrib.messages.middleware.MessageMiddleware', 68 'django.middleware.clickjacking.XFrameOptionsMiddleware', 69 ] 70 71 ROOT_URLCONF = 'PerfectCRM.urls' 72 73 TEMPLATES = [ 74 { 75 'BACKEND': 'django.template.backends.django.DjangoTemplates', 76 # ————————02PerfectCRM建立ADMIN頁面———————— 77 'DIRS': [os.path.join(BASE_DIR, 'templates'), 78 os.path.join(BASE_DIR, 'king_admin/king_templates'), 79 80 # ————————03PerfectCRM建立基本數據———————— 81 os.path.join(BASE_DIR, 'DBadd/DBadd_templates'), 82 # ————————03PerfectCRM建立基本數據———————— 83 # ————————38PerfectCRM實現全局帳號登陸註銷———————— 84 os.path.join(BASE_DIR, 'gbacc/gbacc_templates'), 85 # ————————38PerfectCRM實現全局帳號登陸註銷———————— 86 87 # ————————47PerfectCRM實現CRM客戶報名流程———————— 88 os.path.join(BASE_DIR, 'bpm/bpm_templates'), ] 89 # ————————47PerfectCRM實現CRM客戶報名流程———————— 90 91 , 92 # ————————02PerfectCRM建立ADMIN頁面———————— 93 'APP_DIRS': True, 94 'OPTIONS': { 95 'context_processors': [ 96 'django.template.context_processors.debug', 97 'django.template.context_processors.request', 98 'django.contrib.auth.context_processors.auth', 99 'django.contrib.messages.context_processors.messages', 100 ], 101 }, 102 }, 103 ] 104 105 WSGI_APPLICATION = 'PerfectCRM.wsgi.application' 106 107 108 # Database 109 # https://docs.djangoproject.com/en/2.0/ref/settings/#databases 110 111 DATABASES = { 112 'default': { 113 'ENGINE': 'django.db.backends.sqlite3', 114 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 115 } 116 } 117 118 119 # Password validation 120 # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators 121 122 AUTH_PASSWORD_VALIDATORS = [ 123 { 124 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 125 }, 126 { 127 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 128 }, 129 { 130 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 131 }, 132 { 133 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 134 }, 135 ] 136 137 138 # Internationalization 139 # https://docs.djangoproject.com/en/2.0/topics/i18n/ 140 141 # ————————01PerfectCRM基本配置ADMIN———————— 142 #LANGUAGE_CODE = 'en-us' 143 144 #英文轉中文方法 145 LANGUAGE_CODE = 'zh-Hans' 146 # ————————01PerfectCRM基本配置ADMIN———————— 147 148 TIME_ZONE = 'UTC' 149 150 USE_I18N = True 151 152 USE_L10N = True 153 154 USE_TZ = True 155 156 157 # Static files (CSS, JavaScript, Images) 158 # https://docs.djangoproject.com/en/2.0/howto/static-files/ 159 160 STATIC_URL = '/static/' 161 162 # ————————01PerfectCRM基本配置ADMIN———————— 163 STATICFILES_DIRS = [os.path.join(BASE_DIR,'king_admin/static'), 164 # ————————01PerfectCRM基本配置ADMIN———————— 165 # ————————38PerfectCRM實現全局帳號登陸註銷———————— 166 os.path.join(BASE_DIR, 'gbacc/static'), 167 # ————————38PerfectCRM實現全局帳號登陸註銷———————— 168 169 # ————————47PerfectCRM實現CRM客戶報名流程———————— 170 os.path.join(BASE_DIR, 'bpm/static'),] 171 # ————————47PerfectCRM實現CRM客戶報名流程———————— 172 173 174 # ————————34PerfectCRM實現CRM自定義用戶———————— 175 AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表單 176 # ————————34PerfectCRM實現CRM自定義用戶———————— 177 178 179 180 # ————————44PerfectCRM實現帳號快速註冊登錄———————— 181 # send e-mail 182 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' #email後端 183 EMAIL_USE_TLS = False #是否使用TLS安全傳輸協議 184 EMAIL_USE_SSL = True #是否使用SSL加密,qq企業郵箱要求使用 185 EMAIL_HOST = 'smtp.sina.cn' #發送郵件的郵箱 的 SMTP服務器 #根據狀況從新配置 186 EMAIL_PORT = 465 #發件箱的SMTP服務器端口 #通常不須要修改465 187 EMAIL_HOST_USER = 'perfectcrm@sina.cn' #發送郵件的郵箱帳號 #根據狀況從新配置 #perfectcrm@sina.cn pydjango@sina.cn 188 EMAIL_HOST_PASSWORD = 'admin123456' #發送郵件的郵箱密碼 #根據狀況從新配置 189 190 # ————————44PerfectCRM實現帳號快速註冊登錄———————— 191 192 193 # ————————46PerfectCRM實現登錄後頁面才能訪問———————— 194 LOGIN_URL = '/gbacc/gbacc_login/'# login_url 配置 #默認 /accounts/login/ #注意: / (絕對路徑) 195 # ————————46PerfectCRM實現登錄後頁面才能訪問———————— 196 197 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 198 ENROLLED_DATA='%s/bpm/static/enrolled_data'%BASE_DIR#證件上傳 # 上傳路徑 199 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 200 201 202 # ————————61PerfectCRM實現CRM學生上傳做業———————— 203 HOMEWORK_DATA='%s/bpm/static/homeworks'%BASE_DIR #做業上傳 # 上傳路徑 204 # ————————61PerfectCRM實現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 # ————————61PerfectCRM實現CRM學生上傳做業———————— 265 homework_link = models.TextField(blank=True,null=True)#做業連接 #TextField無限制長度的文本#Django可空#數據庫能夠爲空 266 # ————————61PerfectCRM實現CRM學生上傳做業———————— 267 268 score_choices = (#學習成績 269 (100,"A+"), 270 (90,"A"), 271 (85,"B+"), 272 (80,"B"), 273 (75,"B-"), 274 (70,"C+"), 275 (65,"C"), 276 (40,"C-"), 277 (-20,"D"), 278 (-50,"COPY"), 279 (0,"N/A"),) 280 #PositiveSmallIntegerField正小整數 0 ~ 32767(省空間)#choices是Admin中顯示選擇框的內容,用不變更的數據放在內存中從而避免跨表操做 281 score = models.SmallIntegerField(choices=score_choices) #學習成績 282 283 284 memo = models.TextField(blank=True,null=True)#TextField無限制長度的文本#Django可空#數據庫能夠爲空 285 286 # DateTimeField日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add建立時間(只讀) 287 date = models.DateField(auto_now_add=True)#建立時間(數據庫自增) 288 289 def __str__(self):#__str__()是Python的一個「魔幻」方法,這個方法定義了當object調用str()時應該返回的值。 290 return "%s %s %s" % (self.student, self.course_record, self.score)#返回#格式化字符串#學生名字#開課記錄#學習成績 291 class Meta:#經過一個內嵌類 "class Meta" 給你的 model 定義元數據 292 unique_together = ('student','course_record')#聯合索引#學生名字#開課記錄 293 verbose_name_plural = "09學習紀錄"#verbose_name_plural給你的模型類起一個更可讀的名字 294 295 # ————————34PerfectCRM實現CRM自定義用戶———————— 296 # """10帳號表""" 297 # class UserProfile(models.Model): 298 # from django.contrib.auth.models import User # 使用django內置的用戶表 299 # 300 # #OneToOneField一對一 #User是django Admin裏的帳號表#CASCADE從父表刪除或更新且自動刪除或更新子表中匹配的行。 301 # user = models.OneToOneField(User,on_delete=models.CASCADE)# 用戶名 #建立外鍵,關聯django用戶表 302 # 303 # name = models.CharField(max_length=32) #帳號名(擴展用戶字段)#CharField定長文本 304 # 305 # #ManyToManyField多對多和外鍵工做方式相同,只不過咱們處理的是QuerySet而不是模型實例。#Django可空 306 # roles = models.ManyToManyField("Role",blank=True) #角色(權限) # 雙向一對多==多對多 307 # 308 # def __str__(self):#__str__()是Python的一個「魔幻」方法,這個方法定義了當object調用str()時應該返回的值。 309 # return self.name #返回 #帳號名 310 # class Meta: #經過一個內嵌類 "class Meta" 給你的 model 定義元數據 311 # verbose_name_plural = "10帳號表"#verbose_name_plural給你的模型類起一個更可讀的名字 312 # ————————34PerfectCRM實現CRM自定義用戶———————— 313 314 # ————————34PerfectCRM實現CRM自定義用戶———————— 315 #10帳號表,建立用戶和超級用戶 316 from django.contrib.auth.models import BaseUserManager 317 class UserProfileManager(BaseUserManager): 318 def create_user(self, email, name, password=None): 319 """ 320 建立並保存一個用戶用給定的郵件,日期 321 出生和密碼。 322 """ 323 if not email:#沒有email 報錯 324 raise ValueError('用戶必須有一個電子郵件地址') 325 326 user = self.model( 327 email=self.normalize_email(email),#驗證郵箱格式 328 name=name, 329 ) 330 user.set_password(password)#加密 331 user.is_active = True 332 user.save(using=self._db) 333 return user 334 def create_superuser(self, email, name, password): 335 """ 336 建立並保存一個超級用戶具備給定郵件,日期 337 出生和密碼。 338 """ 339 user = self.create_user(email, 340 password=password, 341 name=name 342 ) 343 user.is_active = True 344 user.is_superuser = True 345 user.save(using=self._db) 346 return user 347 348 """10帳號表""" 349 """ 350 351 #刪除數據庫 352 353 #調用objects = UserProfileManager()#建立帳號 #關聯這個函數 354 355 #運行 Terminal 356 # 生成 數據表 357 # python manage.py makemigrations 358 # 數據表 遷移 359 # python manage.py migrate 360 Django Admin裏帳號密碼重置方法 361 #運行 Terminal 362 python manage.py createsuperuser 363 364 Email address: admin@qq.com 365 用戶名 : admin 366 Password: admin123456 367 Password (again): admin123456 368 """ 369 from django.contrib.auth.models import AbstractBaseUser 370 # ————————35PerfectCRM實現CRM重寫Admin密碼修改———————— 371 from django.utils.translation import ugettext_lazy as _ # 語言國際化 372 from django.utils.safestring import mark_safe 373 from django.contrib.auth.models import PermissionsMixin 374 # class UserProfile(AbstractBaseUser): 375 class UserProfile(AbstractBaseUser,PermissionsMixin): 376 # ————————35PerfectCRM實現CRM重寫Admin密碼修改———————— 377 email=models.EmailField( 378 verbose_name='郵箱帳號', 379 max_length=255, 380 unique=True#惟一 #登錄帳號 381 ) 382 name=models.CharField(max_length=32,verbose_name='用戶名') 383 384 # ————————35PerfectCRM實現CRM重寫Admin密碼修改———————— 385 password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href=\"../password/\">修改密碼</a>''')) 386 # ————————35PerfectCRM實現CRM重寫Admin密碼修改———————— 387 388 is_active = models.BooleanField(default=True,verbose_name='合法帳號')#權限#合法帳號 389 is_superuser = models.BooleanField(default=False,verbose_name='超級帳號') #超級帳號 390 objects = UserProfileManager()#建立帳號 #關聯這個函數 391 USERNAME_FIELD ='email'#指定作爲 #登錄帳號 392 REQUIRED_FIELDS = ['name']#必填字段 393 394 395 # ————————60PerfectCRM實現CRM學生上課記錄———————— 396 stu_account = models.ForeignKey( "Customer", verbose_name='關聯學員賬號', blank=True, null=True, on_delete=models.CASCADE, 397 help_text='報名成功後建立關聯賬戶' ) 398 # ————————60PerfectCRM實現CRM學生上課記錄———————— 399 400 def get_full_name(self): 401 return self.email 402 def get_short_name(self): 403 #用戶確認的電子郵件地址 404 return self.email 405 def __str__(self): 406 return self.name 407 def has_perm(self,perm,obj=None): 408 #指明用戶是否被認爲活躍的。以反選代替刪除賬號。 409 #最簡單的可能的答案:是的,老是 410 return True #有效 帳號 411 def has_module_perms(self, app_label): 412 #指明用戶是否能夠登陸到這個管理站點。 413 # 最簡單的可能的答案:是的,老是 414 return True #職員狀態 415 @property 416 def is_staff(self): 417 '''「用戶的員工嗎?」''' 418 #最簡單的可能的答案:全部管理員都是員工 419 return self.is_superuser#是否是超級用戶狀態 420 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表單 #settings.py 421 # ————————34PerfectCRM實現CRM自定義用戶———————— 422 423 """11角色表""" 424 class Role(models.Model): 425 name = models.CharField(unique=True,max_length=32)#角色名#CharField定長文本#角色名不能夠重複#最長度=32字節 426 def __str__(self):#__str__()是Python的一個「魔幻」方法,這個方法定義了當object調用str()時應該返回的值。 427 return self.name#返回 #角色名 428 class Meta: #經過一個內嵌類 "class Meta" 給你的 model 定義元數據 429 verbose_name_plural = "11角色表" #verbose_name_plural給你的模型類起一個更可讀的名字 430 431 """12標籤表""" 432 class Tag(models.Model): 433 name = models.CharField(max_length=64,unique=True) #標籤名#CharField定長文本#最長度=64字節#不能夠重複 434 def __str__(self): #__str__()是Python的一個「魔幻」方法,這個方法定義了當object調用str()時應該返回的值。 435 return self.name #返回 #標籤名 436 class Meta:#經過一個內嵌類 "class Meta" 給你的 model 定義元數據 437 verbose_name_plural = "12標籤表" #verbose_name_plural給你的模型類起一個更可讀的名字 438 439 # ————————01PerfectCRM基本配置ADMIN————————
1 {#homework_detail.html#} 2 {## ————————61PerfectCRM實現CRM學生上傳做業————————#} 3 {% extends 'bpm_master/bpm_sample.html' %} 4 {% block right-container-content %} {#自定義內容開始 右邊頁面內容#} 5 <div class="panel-default"> 6 <div class="panel-body"> 7 <h4>當前用戶: {{ request.user }} | 學員名字:{{ request.user.stu_account.name }} | 8 學員QQ:{{ request.user.stu_account }}</h4> 9 <div class="row" style="margin-bottom: 20px"> 10 <ol class="breadcrumb"> 11 <li><a href="/bpm/my_course/">個人課程</a></li> 12 <li><a href="/bpm/studyrecords/{{ enroll_obj.id }}/">{{ enroll_obj.enrolled_class }}</a></li> 13 <li><a href="#">第:{{ studyrecord_obj.course_record.day_num }}節</a></li> 14 </ol> 15 </div> 16 <h4>做業標題:{{ studyrecord_obj.course_record.homework_title }}</h4> 17 <h4>做業詳情: 18 <pre>{{ studyrecord_obj.course_record.homework_content }}</pre> 19 </h4> 20 <h4>老師評語: 21 <pre>{{ studyrecord_obj.memo }}</pre> 22 </h4> 23 <h4>本節成績: {{ studyrecord_obj.score }} </h4> 24 <h4>本節做業連接: 25 <pre>{{ studyrecord_obj.homework_link }}</pre> 26 </h4> 27 <form method="post" class="form-horizontal" role="form">{% csrf_token %} 28 <input type="text" class="form-control" name="link" placeholder="做業連接"> 29 <input type="submit" class="btn btn-info" value="提交"> 30 </form> 31 32 33 <hr> 34 <h4>已經上傳的文件: <a id="refresh">刷新</a></h4> 35 <div class="row"> 36 <div class="col-xs-9 col-md-6"> 37 {% for file in file_lists %} 38 <div class="right"> 39 {% for foo in file %} 40 <a>{{ foo }}</a> | 41 {% endfor %} 42 <span class="img_f hide">{{ file.0 }}</span> 43 <a class="del_img">刪除</a> 44 </div> 45 <br> 46 {% endfor %} 47 </div> 48 </div> 49 <h4>請上傳做業</h4> 50 <form action="{{ request.path }}" method="post" id="dropz" enctype="multipart/form-data" 51 class="form-group dropzone">{% csrf_token %} 52 <input type="hidden" name="file_id" ng-model="file_id" id="file_id"/> 53 </form> 54 <h4>課程大綱: 55 <pre>{{ studyrecord_obj.course_record.outline }}</pre> 56 </h4> 57 </div> 58 </div> 59 {% endblock %} 60 61 62 {% block js %} 63 <script> 64 //頁面加載時綁定按鈕點擊事件 65 $("#refresh").click(function () { 66 window.location.reload();//刷新當前頁面. 67 }); 68 69 $('.del_img').click(function () { 70 s = $(this); 71 texts = s.parent().children("span").text(); 72 {# alert(texts);#} 73 $.ajax({ 74 url: "{{ requset.path }}", 75 type: "post", 76 data: {"data": texts}, 77 headers: {'X-CSRFtoken': $.cookie('csrftoken')}, 78 success: function (arg) { 79 if (arg) { 80 alert('刪除成功!'); 81 s.parent('div').addClass('hide'); 82 {# #添加樣式#隱藏#} 83 } 84 } 85 }) 86 }); 87 88 89 Dropzone.autoDiscover = false; 90 appElement = document.querySelector('div .inmodal'); 91 myDropzone = new Dropzone("#dropz", { 92 url: "{{ request.path }}",//文件提交地址 93 paramName: "file", //默認爲file 94 method: "post", //也可用put 95 addRemoveLinks: true, 96 maxFiles: 1,//一次性上傳的文件數量上限 97 maxFilesize: 2, //文件大小,單位:MB 98 acceptedFiles: ".zip,.7z", //上傳的類型 99 {# uploadMultiple: true,#}//上傳多個 100 parallelUploads: 1,//一次上傳的文件數量 101 dictDefaultMessage: '請將做業壓縮打包後上傳', 102 dictMaxFilesExceeded: "您最多隻能上傳1個文件!", 103 dictResponseError: '文件上傳失敗!', 104 dictInvalidFileType: "文件類型只能是*.zip,*.7z。", 105 dictFallbackMessage: "瀏覽器不受支持", 106 dictFileTooBig: "文件過大上傳文件最大支持.", 107 dictRemoveLinks: "刪除", 108 dictCancelUpload: "取消", 109 110 111 init: function () { 112 this.on("addedfile", function (file) { 113 //上傳文件時觸發的事件 114 document.querySelector('div .dz-default').style.display = 'none'; 115 }); 116 this.on("success", function (file, data) { 117 //上傳成功觸發的事件 118 console.log('ok'); 119 }); 120 this.on("error", function (file, data) { 121 //上傳失敗觸發的事件 122 console.log('fail'); 123 var message = ''; 124 //lavarel框架有一個表單驗證, 125 //對於ajax請求,JSON 響應會發送一個 422 HTTP 狀態碼, 126 //對應file.accepted的值是false,在這裏捕捉表單驗證的錯誤提示 127 if (file.accepted) { 128 $.each(data, function (key, val) { 129 message = message + val[0] + ';'; 130 }); 131 //控制器層面的錯誤提示,file.accepted = true的時候; 132 alert(message); 133 } 134 }); 135 this.on("removedfile", function (file) { 136 //刪除文件時觸發的方法 137 document.querySelector('div .dz-default').style.display = 'block'; 138 }); 139 } 140 }); 141 </script> 142 {% endblock %} 143 {## ————————61PerfectCRM實現CRM學生上傳做業————————#}
1 {#studyrecords.html#} 2 {## ————————60PerfectCRM實現CRM學生上課記錄————————#} 3 {% extends 'bpm_master/bpm_sample.html' %} 4 {% load bpm_tags %} 5 {% block right-container-content %} {#自定義內容開始 右邊頁面內容#} 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/student_course/">個人課程</a></li> 12 <li><a href="/bpm/studyrecords/{{ enroll_obj.id }}/">{{ enroll_obj.enrolled_class }}</a></li> 13 </ol> 14 15 <table class="table table-striped table-responsive "> 16 <thead> 17 <tr> 18 <th>課程節次</th> 19 <th>簽到狀態</th> 20 <th>本節做業</th> 21 <th>本節成績</th> 22 <th>本節講師</th> 23 <th>上課日期</th> 24 <th>本節大綱</th> 25 <th>做業標題</th> 26 <th>做業要求</th> 27 </tr> 28 </thead> 29 30 31 <tbody> 32 {% for studyrecord in studyrecordlist %} 33 <tr> 34 <td>{{ studyrecord.course_record.day_num }}</td> 35 {#課程節次#} 36 <td>{{ studyrecord.get_attendance_display }}</td> 37 {#簽到狀態#} 38 <td> 39 <a href="{% url 'homework_detail' enroll_obj.id studyrecord.id %}"> 40 {{ studyrecord.course_record.has_homework }} 41 </a> 42 </td> 43 {#本節做業#} 44 <td>{{ studyrecord.get_score_display }}</td> 45 {#本節成績#} 46 <td>{{ studyrecord.course_record.teacher }}</td> 47 {#本節講師#} 48 <td>{{ studyrecord.course_record.date }}</td> 49 {#上課日期#} 50 <td> 51 <pre style="width: 240px;height: 60px">{{ studyrecord.course_record.outline }}</pre> 52 {#本節大綱#} 53 </td> 54 <td> 55 <pre style="width: 240px;height: 60px">{{ studyrecord.course_record.homework_title }}</pre> 56 {#做業標題#} 57 </td> 58 <td> 59 <pre style="width: 240px;height: 60px">{{ studyrecord.course_record.homework_content }}</pre> 60 {#做業要求#} 61 </td> 62 </tr> 63 {% endfor %} 64 </tbody> 65 </table> 66 </div> 67 </div> 68 {% endblock %} 69 {## ————————60PerfectCRM實現CRM學生上課記錄————————#}