
1 # sales_urls.py 2 # ————————47PerfectCRM實現CRM客戶報名流程———————— 3 from django.conf.urls import url 4 from bpm.sales import sales_views 5 6 urlpatterns = [ 7 8 # ————————75PerfectCRM實現CRM擴展權限———————— 9 url( r'^sales_customer/$', sales_views.sales_customer, name='sales_customer' ), # 銷售自己的客戶庫 10 # ————————75PerfectCRM實現CRM擴展權限———————— 11 12 url(r'^customer/(\d+)/enrollment/$', sales_views.enrollment, name="enrollment"),#客戶招生#報名流程一 下一步 13 14 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 15 # ————————48PerfectCRM實現CRM客戶報名流程學生合同———————— 16 # url(r'^customer/registration/(\d+)/$', sales_views.stu_registration, name="stu_registration"), # 報名流程二 學員簽同合 17 # ————————48PerfectCRM實現CRM客戶報名流程學生合同———————— 18 url(r'^customer/registration/(\d+)/(\w+)/$', sales_views.stu_registration, name="stu_registration"), # 報名流程二 學員簽同合 19 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 20 21 # ————————52PerfectCRM實現CRM客戶報名流程學生合同審核———————— 22 url(r'^contract_prompt/$', sales_views.contract_prompt, name="contract_prompt"), # 報名流程二 提示學員 23 url(r'^not_audit/$', sales_views.not_audit, name="not_audit"), # 報名流程二 未審核 查詢 24 url(r'^contract_review/(\d+)/$', sales_views.contract_review, name="contract_review"), # 報名流程三 審核 25 url(r'^enrollment_rejection/(\d+)/$', sales_views.enrollment_rejection, name="enrollment_rejection"), # 報名流程三 駁回 26 # ————————52PerfectCRM實現CRM客戶報名流程學生合同審核———————— 27 28 ] 29 # ————————47PerfectCRM實現CRM客戶報名流程————————

1 # sales_views.py 2 # ————————47PerfectCRM實現CRM客戶報名流程———————— 3 from django.db import IntegrityError # 主動捕捉錯誤信息 4 from django.shortcuts import render # 頁面返回 5 from crm import models # 數據庫 6 from bpm.bpm_auxiliary import bpm_forms # 自定制 forms 7 from django.contrib.auth.decorators import login_required # 登陸后頁面才能訪問 8 9 # ————————47PerfectCRM實現CRM客戶報名流程———————— 10 from django.core.mail import send_mail 11 # send_mail的參數分別是 郵件標題,郵件內容,發件箱(settings.py中設置過的那個),收件箱列表(可以發送給多個人),失敗靜默(若發送失敗,報錯提示我們) 12 import random 13 import datetime # 獲取時間#登陸過期 14 # ————————74PerfectCRM實現CRM權限和權限組限制訪問URL———————— 15 from permissions.permission import check_permission #權限控制 16 # ————————74PerfectCRM實現CRM權限和權限組限制訪問URL———————— 17 18 19 # ————————75PerfectCRM實現CRM擴展權限———————— 20 #銷售自己的客戶庫 21 def sales_customer(request): 22 user_id=request.user.id #當前登陸的ID 23 return redirect( '/king_admin/crm/customer/?consultant=%s' %(user_id) ) # 跳轉到enrollment_rejection 24 # ————————75PerfectCRM實現CRM擴展權限———————— 25 26 27 # 發送郵件的功能 #驗證碼#密碼 28 class stmp(): 29 def __init__(self): 30 self.emaillist = [] # 發送給誰 31 self.code = None # 驗證碼#密碼 32 33 def stmps(self, request, email, msg_mail): # 傳參數#頁面,session #郵箱,發送給誰 #內容 34 self.emaillist.append(email) # 將郵箱地址添加到調用Django發送郵件功能 35 # ——————生成驗證碼—————— 36 _letter_cases = "abcdefghjkmnpqrstuvwxy" # 小寫字母,去除可能干擾的i,l,o,z 37 _upper_cases = _letter_cases.upper() # 大寫字母 38 _numbers = ''.join(map(str, range(3, 10))) # 數字 39 chars = ''.join((_letter_cases, _upper_cases, _numbers)) # 變成一條字符串 40 list = random.sample(chars, 4) # 從一條字符串隨機選4個字符變成列表 41 self.code = ''.join(list) # 列表變字符串 42 # ——————生成驗證碼—————— 43 # ——————調用Django發送郵件—————— 44 title = 'PerfectCRM項目自動郵件:%s' % self.code # 郵件標題#防止一樣的內容被郵箱屏蔽 45 send_mail(title, # 郵件標題 46 msg_mail, # 驗證碼內容 47 'perfectcrm@sina.cn', # 發送的郵箱 #根據情況重新配置 48 self.emaillist, # 接受的郵箱 49 fail_silently=False, # 靜默,拋出異常 50 ) 51 print('發送郵件成功!沒收到要換標題!檢查發送郵箱的配置!') 52 # ——————調用Django發送郵件—————— 53 # ————————47PerfectCRM實現CRM客戶報名流程———————— 54 # ————————47PerfectCRM實現CRM客戶報名流程———————— 55 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 56 import random # 隨機 57 import string # 字母 數字 58 from django.core.cache import cache # 緩存 59 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 60 61 # 報名填寫 銷售 62 @login_required # 登陸后頁面才能訪問 63 @check_permission #權限控制 64 def enrollment(request, customer_id): 65 msgs = {} # 錯誤信息 66 customer_obj = models.Customer.objects.get(id=customer_id) # 取到客戶信息記錄 #返回到頁面#報名人 67 consultant_obj = models.UserProfile.objects.get(id=request.user.id) # 報名課程顧問 68 69 stmp_mail = {} # 郵件發送成功 70 stmpemail = stmp() # 實例化發送郵件的功能 71 email = request.POST.get('email') # 讓頁面POST提交的值,在頁面GET后仍然存在顯示 72 if request.method == "POST": 73 enroll_form = bpm_forms.EnrollmentForm(request.POST) # 獲取數據 74 if enroll_form.is_valid(): # 表單驗證 75 76 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 77 # msg = "http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/" 78 msg = "http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/{random_str}/ " 79 random_str = ''.join(random.sample(string.ascii_lowercase + string.digits, 8)) # 生成8位隨機字符串 #URL使用 80 url_str = '''customer/registration/{enroll_obj_id}/{random_str}/''' # 報名鏈接 81 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 82 83 try: 84 enroll_form.cleaned_data['customer'] = customer_obj # 添加學員對象 記錄 #報名人 85 enroll_form.cleaned_data['consultant'] = consultant_obj # 報名課程顧問 86 enroll_obj = models.Enrollment.objects.create(**enroll_form.cleaned_data) # 創建記錄 87 88 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 89 # msgs['msg']=msg.format(enroll_obj_id=enroll_obj.id)#報名記錄對應的id,隨機字符串,報名鏈接 90 sort_url = enroll_obj.id # 獲取報名表對應的ID 91 cache.set(enroll_obj.id, random_str, 61000) # 加入過期時間 #URL使用 # cache緩存 92 msgs['msg'] = msg.format(enroll_obj_id=enroll_obj.id, random_str=random_str) # 報名記錄對應的id,隨機字符串,報名鏈接 93 url_str = url_str.format(enroll_obj_id=enroll_obj.id, random_str=random_str) # 報名鏈接 94 print(url_str) 95 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 96 except IntegrityError as e: 97 # 取到這條記錄 98 enroll_obj = models.Enrollment.objects.get(customer_id=customer_obj.id, 99 enrolled_class_id=enroll_form.cleaned_data[ 100 'enrolled_class'].id) 101 102 # ————————52PerfectCRM實現CRM客戶報名流程學生合同審核———————— 103 if enroll_obj.contract_agreed:#學員已經同意合同,提交了身份證 104 #return redirect('/crm/contract_review/%s/'%enroll_obj.id)#跳轉到審核頁面 105 return render(request,'bpm_sales/contract_prompt.html',locals())#跳轉提示頁面 106 # ————————52PerfectCRM實現CRM客戶報名流程學生合同審核———————— 107 108 enroll_form.add_error('__all__', '記錄已經存在,不能重復創建!') 109 110 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 111 # msgs['msg']=msg.format(enroll_obj_id=enroll_obj.id)#報名記錄對應的id 112 cache.set(enroll_obj.id, random_str, 61000) # 加入過期時間 #URL使用 # cache緩存 113 msgs['msg'] = msg.format(enroll_obj_id=enroll_obj.id, random_str=random_str) # 報名記錄對應的id 114 url_str = url_str.format(enroll_obj_id=enroll_obj.id, random_str=random_str) # 報名鏈接 115 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 116 117 if email: 118 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 119 # msg_mail = "http://127.0.0.1:8000/bpm/customer/registration/%s" %enroll_obj.id 120 msg_mail = "http://127.0.0.1:8000/bpm/customer/registration/%s/%s" %(enroll_obj.id,random_str) 121 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 122 stmpemail.stmps(request, email, msg_mail) # 發送郵件 123 stmp_mail['ok'] = "郵件已發送成功!" 124 125 else: 126 enroll_form = bpm_forms.EnrollmentForm() # modelform表單 127 return render(request, 'bpm_sales/enrollment.html', locals()) 128 # ————————47PerfectCRM實現CRM客戶報名流程———————— 129 130 131 # ————————48PerfectCRM實現CRM客戶報名流程學生合同———————— 132 #學員合同簽定 133 134 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 135 import os 136 from PerfectCRM import settings 137 import json 138 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 139 140 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 141 from django.shortcuts import HttpResponse #頁面返回 142 # def stu_registration(request,enroll_id): 143 def stu_registration(request,enroll_id,random_str): 144 # enroll_obj=models.Enrollment.objects.get(id=enroll_id)#獲取報名記錄 145 if cache.get(enroll_id) == random_str: # 判斷鏈接失效了沒有 146 enroll_obj = models.Enrollment.objects.get(id=enroll_id) # 報名記錄 147 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 148 149 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 150 enrolled_path='%s/%s/'%(settings.ENROLLED_DATA,enroll_id)#證件上傳路徑 151 img_file_len=0 #文件 152 if os.path.exists(enrolled_path):#判斷目錄是否存在 153 img_file_list=os.listdir(enrolled_path)#取目錄 下的文件 154 img_file_len=len(img_file_list) 155 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 156 157 # ————————49PerfectCRM實現CRM客戶報名流程學生合同表單驗證———————— 158 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 159 if request.method == "POST": 160 161 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 162 ret=False 163 data=request.POST.get('data') 164 if data:#如果有刪除動作 165 del_img_path="%s/%s/%s"%(settings.ENROLLED_DATA,enroll_id,data)#路徑 166 print(del_img_path,'=-=-=-=-=-=') 167 os.remove(del_img_path) 168 ret=True 169 return HttpResponse(json.dumps(ret)) 170 if request.is_ajax():#ajax上傳圖片 #異步提交 171 print('ajax上傳圖片 #異步提交中。。。 ',request.FILES) 172 enroll_data_dir="%s/%s"%(settings.ENROLLED_DATA,enroll_id)#路徑 #重要信息不能放在靜態文件中 173 if not os.path.exists(enroll_data_dir):#如果不存目錄 174 os.makedirs(enroll_data_dir,exist_ok=True)#創建目錄 175 for k,file_obj in request.FILES.items(): #循環字典 #上傳的文件 176 with open("%s/%s"%(enroll_data_dir,file_obj.name),'wb') as f: #打開一個文件#路徑#獲取文件名 177 for chunk in file_obj.chunks():#循環寫入文件 # chunks塊 178 f.write(chunk) #保存文件 179 return HttpResponse('上傳完成!') 180 # ————————51PerfectCRM實現CRM客戶報名流程學生合同上傳照片———————— 181 182 customer_form = bpm_forms.CustomerForm(request.POST, instance=enroll_obj.customer) # 生成表單驗證 183 if customer_form.is_valid(): # 表單驗證通過 184 customer_form.save() # 保存 185 enroll_obj.contract_agreed = True # 同意協議 186 enroll_obj.save() # 保存 187 status = 1 # 修改報名狀態 # 1 已經報名 188 return render(request, 'bpm_sales/stu_registration.html', locals()) 189 190 else: 191 if enroll_obj.contract_agreed == True: # 如果協議已經簽訂 192 status = 1 # 修改報名狀態 # 1 已經報名 193 else: 194 status = 0 195 customer_form = bpm_forms.CustomerForm(instance=enroll_obj.customer) # 生成表單 196 # customer_form = bpm_forms.CustomerForm(instance=enroll_obj.customer) # 生成表單 197 # ————————49PerfectCRM實現CRM客戶報名流程學生合同表單驗證———————— 198 199 return render(request,'bpm_sales/stu_registration.html',locals()) 200 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 201 # ————————48PerfectCRM實現CRM客戶報名流程學生合同———————— 202 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 203 else: 204 return HttpResponse('鏈接失效,非法鏈接,請自重!') 205 # ————————50PerfectCRM實現CRM客戶報名流程學生合同URL隨機碼———————— 206 207 208 # ————————52PerfectCRM實現CRM客戶報名流程學生合同審核———————— 209 from django.shortcuts import redirect 210 #查詢流程提示頁面 211 def contract_prompt(request,enroll_id): 212 enroll_obj=models.Enrollment.objects.get(id=enroll_id)#取對象 213 enroll_form= bpm_forms.EnrollmentForm(instance=enroll_obj)#報名表對象 214 customers_form= bpm_forms.CustomerForm(instance=enroll_obj.customer)#學員的信息 215 return render(request,'bpm_sales/contract_prompt.html',locals()) 216 217 # ————————68PerfectCRM實現CRM業務流程(bpm)報名繳費分頁———————— 218 from bpm.bpm_auxiliary.pagination import Page #分頁 219 # ————————68PerfectCRM實現CRM業務流程(bpm)報名繳費分頁———————— 220 # #待審核 221 @login_required # 登陸后頁面才能訪問 222 @check_permission #權限控制 223 def not_audit(request): 224 # ————————68PerfectCRM實現CRM業務流程(bpm)報名繳費分頁———————— 225 # sign=models.Enrollment.objects.all()#所有的報名表 226 # print(sign,'sign----->') 227 sign=models.Enrollment.objects.filter(contract_agreed=True,contract_approved=False).all()#所有的報名表 228 229 page = Page(request.GET.get('p', 1), len(sign)) #當前頁數 默認為1 #總數量 230 sign = sign[page.start:page.end] # 切片取當前頁的數據 231 page_str = page.page_str('/bpm/not_audit/') #總頁數 傳入url 232 # ————————68PerfectCRM實現CRM業務流程(bpm)報名繳費分頁———————— 233 return render(request, 'bpm_sales/not_audit.html', locals())# 234 235 #審核合同 236 @login_required # 登陸后頁面才能訪問 237 @check_permission #權限控制 238 def contract_review(request,enroll_id): 239 enroll_obj=models.Enrollment.objects.get(id=enroll_id)#取對象 240 contract_review = request.user.name #當前登陸人 #合同審核人 241 #payment_form=forms.PaymentForm()#生成表單 242 enroll_form= bpm_forms.EnrollmentForm(instance=enroll_obj)#報名表對象 243 customer_form= bpm_forms.CustomerForm(instance=enroll_obj.customer)#學員的信息 244 enrolled_path='%s/%s/'%(settings.ENROLLED_DATA,enroll_id)#證件上傳路徑 245 if os.path.exists(enrolled_path):#判斷目錄是否存在 246 file_list=os.listdir(enrolled_path)#取目錄 下的文件 247 imgs_one=file_list[0] #圖片1 248 imgs_two=file_list[1] #圖片2 249 if request.method=="POST": 250 enroll_obj.contract_approved = True # 審核通過 251 enroll_obj.save() #保存 252 enroll = models.Enrollment.objects.filter(id=enroll_id).update(contract_review=contract_review)#合同審核人 253 print('審核通過。。。') 254 return redirect('/bpm/not_audit/')#跳轉到待審核 255 return render(request, 'bpm_sales/contract_review.html', locals())# 256 #駁回合同 257 def enrollment_rejection(request,enroll_id): 258 enroll_obj=models.Enrollment.objects.get(id=enroll_id)#報名表的對象 259 enroll_obj.contract_agreed=False#修改學員已經同意核同 260 enroll_obj.save() #保存 261 return redirect('/bpm/customer/%s/enrollment/'%enroll_obj.customer.id)#跳轉到enrollment_rejection 262 # ————————52PerfectCRM實現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 390 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 391 branch = models.ForeignKey( "Branch", verbose_name="所屬校區", blank=True, null=True, on_delete=models.CASCADE ) 392 roles = models.ManyToManyField( 'Role', verbose_name="角色", blank=True ) 393 memo = models.TextField( blank=True, null=True, default=None, verbose_name="備注" ) 394 from django.utils import timezone 395 date_joined = models.DateTimeField( verbose_name="創建時間", default=timezone.now ) 396 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 397 398 # ————————35PerfectCRM實現CRM重寫Admin密碼修改———————— 399 password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href=\"../password/\">修改密碼</a>''')) 400 # ————————35PerfectCRM實現CRM重寫Admin密碼修改———————— 401 402 is_active = models.BooleanField(default=True,verbose_name='合法賬號')#權限#合法賬號 403 is_superuser = models.BooleanField(default=False,verbose_name='超級賬號') #超級賬號 404 objects = UserProfileManager()#創建賬號 #關聯這個函數 405 USERNAME_FIELD ='email'#指定做為 #登陸賬號 406 REQUIRED_FIELDS = ['name']#必填字段 407 408 409 # ————————60PerfectCRM實現CRM學生上課記錄———————— 410 stu_account = models.ForeignKey( "Customer", verbose_name='關聯學員帳號', blank=True, null=True, on_delete=models.CASCADE, 411 help_text='報名成功后創建關聯帳戶' ) 412 # ————————60PerfectCRM實現CRM學生上課記錄———————— 413 414 def get_full_name(self): 415 return self.email 416 def get_short_name(self): 417 #用戶確認的電子郵件地址 418 return self.email 419 def __str__(self): 420 return self.name 421 def has_perm(self,perm,obj=None): 422 #指明用戶是否被認為活躍的。以反選代替刪除帳號。 423 #最簡單的可能的答案:是的,總是 424 return True #有效 賬號 425 def has_module_perms(self, app_label): 426 #指明用戶是否可以登錄到這個管理站點。 427 # 最簡單的可能的答案:是的,總是 428 return True #職員狀態 429 @property 430 def is_staff(self): 431 '''“用戶的員工嗎?”''' 432 #最簡單的可能的答案:所有管理員都是員工 433 return self.is_superuser#是不是超級用戶狀態 434 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表單 #settings.py 435 # ————————34PerfectCRM實現CRM自定義用戶———————— 436 # ————————74PerfectCRM實現CRM權限和權限組限制URL———————— 437 class Meta: 438 verbose_name_plural = '10CRM賬戶表' 439 permissions = ( 440 ('crm_010101_all_table_data_list_GET', '010101_全部查看數據_GET'), 441 ('crm_010102_all_table_data_list_POST', '010102_全部查看數據_POST'), 442 ('crm_010103_all_table_add_GET', '010103_全部添加數據_GET'), 443 ('crm_010104_all_table_add_POST', '010104_全部添加數據_POST'), 444 ('crm_010105_all_table_change_GET', '010105_全部修改數據_GET'), 445 ('crm_010106_all_table_change_POST', '010106_全部修改數據_POST'), 446 ('crm_010107_all_table_delete_GET', '010107_全部刪除數據_GET'), 447 ('crm_010108_all_table_delete_POST', '010108_全部刪除數據_POST'), 448 ('crm_010109_all_password_reset_GET', '010109_全部密碼重置_GET'), 449 ('crm_010110_all_password_reset_POST', '010110_全部密碼重置_POST'), 450 451 ('crm_010201_only_view_Branch_GET', '010201_只能查看校區表_GET'), 452 ('crm_010202_only_view_Branch_POST', '010202_只能查看校區表_POST'), 453 ('crm_010203_only_add_Branch_GET', '010203_只能添加校區表_GET'), 454 ('crm_010204_only_add_Branch_POST', '010204_只能添加校區表_POST'), 455 ('crm_010205_only_change_Branch_GET', '010205_只能修改校區表_GET'), 456 ('crm_010206_only_change_Branch_POST', '010206_只能修改校區表_POST'), 457 ('crm_010207_only_delete_Branch_GET', '010207_只能刪除校區表_GET'), 458 ('crm_010208_only_delete_Branch_POST', '010208_只能刪除校區表_POST'), 459 460 ('crm_010301_only_view_ClassList_GET', '010301_只能查看班級表_GET'), 461 ('crm_010302_only_view_ClassList_POST', '010302_只能查看班級表_POST'), 462 ('crm_010303_only_add_ClassList_GET', '010303_只能添加班級表_GET'), 463 ('crm_010304_only_add_ClassList_POST', '010304_只能添加班級表_POST'), 464 ('crm_010305_only_change_ClassList_GET', '010305_只能修改班級表_GET'), 465 ('crm_010306_only_change_ClassList_POST', '010306_只能修改班級表_POST'), 466 ('crm_010307_only_delete_ClassList_GET', '010307_只能刪除班級表_GET'), 467 ('crm_010308_only_delete_ClassList_POST', '010308_只能刪除班級表_POST'), 468 469 ('crm_010401_only_view_Course_GET', '010401_只能查看課程表_GET'), 470 ('crm_010402_only_view_Course_POST', '010402_只能查看課程表_POST'), 471 ('crm_010403_only_add_Course_GET', '010403_只能添加課程表_GET'), 472 ('crm_010404_only_add_Course_POST', '010404_只能添加課程表_POST'), 473 ('crm_010405_only_change_Course_GET', '010405_只能修改課程表_GET'), 474 ('crm_010406_only_change_Course_POST', '010406_只能修改課程表_POST'), 475 ('crm_010407_only_delete_Course_GET', '010407_只能刪除課程表_GET'), 476 ('crm_010408_only_delete_Course_POST', '010408_只能刪除課程表_POST'), 477 478 ('crm_010501_only_view_Customer_GET', '010501_只能查看客戶表_GET'), 479 ('crm_010502_only_view_Customer_POST', '010502_只能查看客戶表_POST'), 480 ('crm_010503_only_add_Customer_GET', '010503_只能添加客戶表_GET'), 481 ('crm_010504_only_add_Customer_POST', '010504_只能添加客戶表_POST'), 482 ('crm_010505_only_change_Customer_GET', '010505_只能修改客戶表_GET'), 483 ('crm_010506_only_change_Customer_POST', '010506_只能修改客戶表_POST'), 484 ('crm_010507_only_delete_Customer_GET', '010507_只能刪除客戶表_GET'), 485 ('crm_010508_only_delete_Customer_POST', '010508_只能刪除客戶表_POST'), 486 487 ('crm_010601_only_view_CustomerFollowUp_GET', '010601_只能查看跟進表_GET'), 488 ('crm_010602_only_view_CustomerFollowUp_POST', '010602_只能查看跟進表_POST'), 489 ('crm_010603_only_add_CustomerFollowUp_GET', '010603_只能添加跟進表_GET'), 490 ('crm_010604_only_add_CustomerFollowUp_POST', '010604_只能添加跟進表_POST'), 491 ('crm_010605_only_change_CustomerFollowUp_GET', '010605_只能修改跟進表_GET'), 492 ('crm_010606_only_change_CustomerFollowUp_POST', '010606_只能修改跟進表_POST'), 493 ('crm_010607_only_delete_CustomerFollowUp_GET', '010607_只能刪除跟進表_GET'), 494 ('crm_010608_only_delete_CustomerFollowUp_POST', '010608_只能刪除跟進表_POST'), 495 496 ('crm_010701_only_view_Enrollment_GET', '010701_只能查看報名表_GET'), 497 ('crm_010702_only_view_Enrollment_POST', '010702_只能查看報名表_POST'), 498 ('crm_010703_only_add_Enrollment_GET', '010703_只能添加報名表_GET'), 499 ('crm_010704_only_add_Enrollment_POST', '010704_只能添加報名表_POST'), 500 ('crm_010705_only_change_Enrollment_GET', '010705_只能修改報名表_GET'), 501 ('crm_010706_only_change_Enrollment_POST', '010706_只能修改報名表_POST'), 502 ('crm_010707_only_delete_Enrollment_GET', '010707_只能刪除報名表_GET'), 503 ('crm_010708_only_delete_Enrollment_POST', '010708_只能刪除報名表_POST'), 504 505 ('crm_010801_only_view_Payment_GET', '010801_只能查看繳費表_GET'), 506 ('crm_010802_only_view_Payment_POST', '010802_只能查看繳費表_POST'), 507 ('crm_010803_only_add_Payment_GET', '010803_只能添加繳費表_GET'), 508 ('crm_010804_only_add_Payment_POST', '010804_只能添加繳費表_POST'), 509 ('crm_010805_only_change_Payment_GET', '010805_只能修改繳費表_GET'), 510 ('crm_010806_only_change_Payment_POST', '010806_只能修改繳費表_POST'), 511 ('crm_010807_only_delete_Payment_GET', '010807_只能刪除繳費表_GET'), 512 ('crm_010808_only_delete_Payment_POST', '010808_只能刪除繳費表_POST'), 513 514 ('crm_010901_only_view_CourseRecord_GET', '010901_只能查看上課表_GET'), 515 ('crm_010902_only_view_CourseRecord_POST', '010902_只能查看上課表_POST'), 516 ('crm_010903_only_add_CourseRecord_GET', '010903_只能添加上課表_GET'), 517 ('crm_010904_only_add_CourseRecord_POST', '010904_只能添加上課表_POST'), 518 ('crm_010905_only_change_CourseRecord_GET', '010905_只能修改上課表_GET'), 519 ('crm_010906_only_change_CourseRecord_POST', '010906_只能修改上課表_POST'), 520 ('crm_010907_only_delete_CourseRecord_GET', '010907_只能刪除上課表_GET'), 521 ('crm_010908_only_delete_CourseRecord_POST', '010908_只能刪除上課表_POST'), 522 523 ('crm_011001_only_view_StudyRecord_GET', '011001_只能查看學習表_GET'), 524 ('crm_011002_only_view_StudyRecord_POST', '011002_只能查看學習表_POST'), 525 ('crm_011003_only_add_StudyRecord_GET', '011003_只能添加學習表_GET'), 526 ('crm_011004_only_add_StudyRecord_POST', '011004_只能添加學習表_POST'), 527 ('crm_011005_only_change_StudyRecord_GET', '011005_只能修改學習表_GET'), 528 ('crm_011006_only_change_StudyRecord_POST', '011006_只能修改學習表_POST'), 529 ('crm_011007_only_delete_StudyRecord_GET', '011007_只能刪除學習表_GET'), 530 ('crm_011008_only_delete_StudyRecord_POST', '011008_只能刪除學習表_POST'), 531 532 ('crm_011101_only_view_UserProfile_GET', '011101_只能查看賬號表_GET'), 533 ('crm_011102_only_view_UserProfile_POST', '011102_只能查看賬號表_POST'), 534 ('crm_011103_only_add_UserProfile_GET', '011103_只能添加賬號表_GET'), 535 ('crm_011104_only_add_UserProfile_POST', '011104_只能添加賬號表_POST'), 536 ('crm_011105_only_change_UserProfile_GET', '011105_只能修改賬號表_GET'), 537 ('crm_011106_only_change_UserProfile_POST', '011106_只能修改賬號表_POST'), 538 ('crm_011107_only_delete_UserProfile_GET', '011107_只能刪除賬號表_GET'), 539 ('crm_011108_only_delete_UserProfile_POST', '011108_只能刪除賬號表_POST'), 540 541 ('crm_011201_only_view_Role_GET', '011201_只能查看角色表_GET'), 542 ('crm_011202_only_view_Role_POST', '011202_只能查看角色表_POST'), 543 ('crm_011203_only_add_Role_GET', '011203_只能添加角色表_GET'), 544 ('crm_011204_only_add_Role_POST', '011204_只能添加角色表_POST'), 545 ('crm_011205_only_change_Role_GET', '011205_只能修改角色表_GET'), 546 ('crm_011206_only_change_Role_POST', '011206_只能修改角色表_POST'), 547 ('crm_011207_only_delete_Role_GET', '011207_只能刪除角色表_GET'), 548 ('crm_011208_only_delete_Role_POST', '011208_只能刪除角色表_POST'), 549 550 ('crm_011301_only_view_Tag_GET', '011301_只能查看標簽表_GET'), 551 ('crm_011302_only_view_Tag_POST', '011302_只能查看標簽表_POST'), 552 ('crm_011303_only_add_Tag_GET', '011303_只能添加標簽表_GET'), 553 ('crm_011304_only_add_Tag_POST', '011304_只能添加標簽表_POST'), 554 ('crm_011305_only_change_Tag_GET', '011305_只能修改標簽表_GET'), 555 ('crm_011306_only_change_Tag_POST', '011306_只能修改標簽表_POST'), 556 ('crm_011307_only_delete_Tag_GET', '011307_只能刪除標簽表_GET'), 557 ('crm_011308_only_delete_Tag_POST', '011308_只能刪除標簽表_POST'), 558 559 ('crm_011401_only_view_FirstLayerMenu_GET', '011401_只能查看一層菜單_GET'), 560 ('crm_011402_only_view_FirstLayerMenu_POST', '011402_只能查看一層菜單_POST'), 561 ('crm_011403_only_add_FirstLayerMenu_GET', '011403_只能添加一層菜單_GET'), 562 ('crm_011404_only_add_FirstLayerMenu_POST', '011404_只能添加一層菜單_POST'), 563 ('crm_011405_only_change_FirstLayerMenu_GET', '011405_只能修改一層菜單_GET'), 564 ('crm_011406_only_change_FirstLayerMenu_POST', '011406_只能修改一層菜單_POST'), 565 ('crm_011407_only_delete_FirstLayerMenu_GET', '011407_只能刪除一層菜單_GET'), 566 ('crm_011408_only_delete_FirstLayerMenu_POST', '011408_只能刪除一層菜單_POST'), 567 568 ('crm_011501_only_view_SubMenu_GET', '011501_只能查看二層菜單_GET'), 569 ('crm_011502_only_view_SubMenu_POST', '011502_只能查看二層菜單_POST'), 570 ('crm_011503_only_add_SubMenu_GET', '011503_只能添加二層菜單_GET'), 571 ('crm_011504_only_add_SubMenu_POST', '011504_只能添加二層菜單_POST'), 572 ('crm_011505_only_change_SubMenu_GET', '011505_只能修改二層菜單_GET'), 573 ('crm_011506_only_change_SubMenu_POST', '011506_只能修改二層菜單_POST'), 574 ('crm_011507_only_delete_SubMenu_GET', '011507_只能刪除二層菜單_GET'), 575 ('crm_011508_only_delete_SubMenu_POST', '011508_只能刪除二層菜單_POST'), 576 577 ('crm_011601_only_view_Groups_GET', '011601_只能查看權限組_GET'), 578 ('crm_011602_only_view_Groups_POST', '011602_只能查看權限組_POST'), 579 ('crm_011603_only_add_Groups_GET', '011603_只能添加權限組_GET'), 580 ('crm_011604_only_add_Groups_POST', '011604_只能添加權限組_POST'), 581 ('crm_011605_only_change_Groups_GET', '011605_只能修改權限組_GET'), 582 ('crm_011606_only_change_Groups_POST', '011606_只能修改權限組_POST'), 583 ('crm_011607_only_delete_Groups_GET', '011607_只能刪除權限組_GET'), 584 ('crm_011608_only_delete_Groups_POST', '011608_只能刪除權限組_POST'), 585 586 ('crm_011701_own_password_reset_GET', '011701_自己密碼重置_GET'), 587 ('crm_011702_own_password_reset_POST', '011702_自己密碼重置_POST'), 588 589 ('crm_020101_all_not_audit_GET', '020101_銷售查看全部的客戶未審核_GET'), 590 ('crm_020103_all_enrollment_GET', '020103_銷售給全部的客戶報名課程_GET'), 591 ('crm_020104_all_enrollment_POST', '020104_銷售給全部的客戶報名課程_POST'), 592 ('crm_020105_all_contract_review_GET', '020105_銷售給全部的客戶審核合同_GET'), 593 ('crm_020116_all_contract_review_POST', '020116_銷售給全部的客戶審核合同_POST'), 594 595 ('crm_020201_own_enrollment_GET', '020201_銷售給自己的客戶報名課程_GET'), 596 ('crm_020202_own_enrollment_POST', '020202_銷售給自己的客戶報名課程_POST'), 597 ('crm_020203_own_contract_review_GET', '020203_銷售給自己的客戶審核合同_GET'), 598 ('crm_020204_own_contract_review_POST', '020204_銷售給自己的客戶審核合同_POST'), 599 600 ('crm_030101_all_not_payment_GET', '030101_財務查看全部的客戶未繳費_GET'), 601 ('crm_030102_all_not_payment_POST', '030102_財務查看全部的客戶未繳費_POST'), 602 ('crm_030103_all_already_payment_GET', '030103_財務查看全部的客戶已繳費_GET'), 603 ('crm_030104_all_already_payment_POST', '030104_財務查看全部的客戶已繳費_POST'), 604 ('crm_030105_all_payment_GET', '030105_財務進行全部的客戶繳費_GET'), 605 ('crm_030106_all_payment_POST', '030106_財務進行全部的客戶繳費_POST'), 606 607 ('crm_040101_own_student_course_GET', '040101_學生查看自己的課程_GET'), 608 ('crm_040102_own_student_course_POST', '040102_學生查看自己的課程_POST'), 609 ('crm_040103_own_studyrecords_GET', '040103_學生自己的上課記錄_GET'), 610 ('crm_040104_own_studyrecords_POST', '040104_學生自己的上課記錄_POST'), 611 ('crm_040105_own_homework_detail_GET', '040105_學生自己的作業詳情_GET'), 612 ('crm_040106_own_homework_detail_POST', '040106_學生自己的作業詳情_POST'), 613 614 ('crm_050101_own_teacher_class_GET', '050101_講師查看自己的班級_GET'), 615 ('crm_050102_own_teacher_class_POST', '050102_講師查看自己的班級_POST'), 616 ('crm_050103_own_teacher_class_detail_GET', '050103_講師查看自己的課節詳情_GET'), 617 ('crm_050104_own_teacher_class_detail_POST', '050104_講師查看自己的課節詳情_POST'), 618 ('crm_050105_own_teacher_lesson_detail_GET', '050105_講師查看自己的課節學員_GET'), 619 ('crm_050106_own_teacher_lesson_detail_POST', '050106_講師查看自己的課節學員_POST'), 620 ('crm_050107_own_howk_down_GET', '050107_講師自己的學員作業下載_GET'), 621 ('crm_050108_own_howk_down_POST', '050108_講師自己的學員作業下載_POST'), 622 623 ('crm_060101_own_coursetop_details_GET', '060101_講師查看自己的班級排名詳情_GET'), 624 ('crm_060102_own_coursetop_details_POST', '060102_講師查看自己的班級排名詳情_POST'), 625 ('crm_060103_own_coursetop_score_GET', '060103_講師查看自己的班級分數排行_GET'), 626 ('crm_060104_own_coursetop_score_POST', '060104_講師查看自己的班級排分數排行_POST'), 627 ('crm_060105_own_coursetop_homework_GET', '060105_講師查看自己的班級作業排行_GET'), 628 ('crm_060106_own_coursetop_homework_POST', '060106_講師查看自己的班級作業排行_POST'), 629 ('crm_060107_own_coursetop_attendance_GET', '060107_講師查看自己的班級出勤排行_GET'), 630 ('crm_060108_own_coursetop_attendance_POST', '060108_講師查看自己的班級出勤排行_POST'), 631 632 ) 633 # ————————74PerfectCRM實現CRM權限和權限組限制URL———————— 634 # ————————74PerfectCRM實現CRM權限和權限組限制URL———————— 635 """15權限組""" 636 from django.contrib.auth.models import Group 637 class Groups(Group): 638 class Meta: 639 verbose_name_plural = '15權限組' 640 # ————————74PerfectCRM實現CRM權限和權限組限制URL———————— 641 # ————————75PerfectCRM實現CRM擴展權限———————— 642 from django.contrib.auth.models import Permission 643 class Permissions(Permission): 644 dic_name = models.CharField(_('dic_name'), max_length=255) 645 class Meta: 646 verbose_name_plural = "16擴展權限" 647 # ————————75PerfectCRM實現CRM擴展權限———————— 648 649 650 """11角色表""" 651 class Role(models.Model): 652 name = models.CharField(unique=True,max_length=32)#角色名#CharField定長文本#角色名不可以重復#最長度=32字節 653 654 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 655 menus = models.ManyToManyField('FirstLayerMenu',verbose_name='一層菜單',blank=True) 656 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 657 658 def __str__(self):#__str__()是Python的一個“魔幻”方法,這個方法定義了當object調用str()時應該返回的值。 659 return self.name#返回 #角色名 660 class Meta: #通過一個內嵌類 "class Meta" 給你的 model 定義元數據 661 verbose_name_plural = "11角色表" #verbose_name_plural給你的模型類起一個更可讀的名字 662 663 664 """12標簽表""" 665 class Tag(models.Model): 666 name = models.CharField(max_length=64,unique=True) #標簽名#CharField定長文本#最長度=64字節#不可以重復 667 def __str__(self): #__str__()是Python的一個“魔幻”方法,這個方法定義了當object調用str()時應該返回的值。 668 return self.name #返回 #標簽名 669 class Meta:#通過一個內嵌類 "class Meta" 給你的 model 定義元數據 670 verbose_name_plural = "12標簽表" #verbose_name_plural給你的模型類起一個更可讀的名字 671 672 # ————————01PerfectCRM基本配置ADMIN———————— 673 674 675 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 676 """13一層菜單名""" 677 class FirstLayerMenu(models.Model): 678 '''第一層側邊欄菜單''' 679 name = models.CharField('一層菜單名',max_length=64) 680 url_type_choices = ((0,'相關的名字'),(1,'固定的URL')) 681 url_type = models.SmallIntegerField(choices=url_type_choices,default=0) 682 url_name = models.CharField(max_length=64,verbose_name='一層菜單路徑') 683 order = models.SmallIntegerField(default=0,verbose_name='菜單排序') 684 sub_menus = models.ManyToManyField('SubMenu',blank=True) 685 686 def __str__(self): 687 return self.name 688 689 class Meta: 690 verbose_name_plural = "13第一層菜單" 691 692 """14二層菜單名""" 693 class SubMenu(models.Model): 694 '''第二層側邊欄菜單''' 695 name = models.CharField('二層菜單名', max_length=64) 696 url_type_choices = ((0,'相關的名字'),(1,'固定的URL')) 697 url_type = models.SmallIntegerField(choices=url_type_choices,default=0) 698 url_name = models.CharField(max_length=64, verbose_name='二層菜單路徑') 699 order = models.SmallIntegerField(default=0, verbose_name='菜單排序') 700 701 def __str__(self): 702 return self.name 703 704 class Meta: 705 verbose_name_plural = "14第二層菜單" 706 # ————————72PerfectCRM實現CRM動態菜單和角色————————

1 # kingadmin.py 2 # ————————04PerfectCRM實現King_admin注冊功能———————— 3 from crm import models 4 #print("kingadmin crm",models.Customer) 5 6 # ————————05PerfectCRM實現King_admin注冊功能獲取內存———————— 7 # from king_admin.base_admin import register,BaseAdmin 8 from king_admin.base_admin import site,BaseAdmin 9 # ————————05PerfectCRM實現King_admin注冊功能獲取內存———————— 10 11 # ————————24PerfectCRM實現King_admin自定義操作數據———————— 12 from django.shortcuts import render 13 # ————————24PerfectCRM實現King_admin自定義操作數據———————— 14 15 # ————————28PerfectCRM實現King_admin編輯限制———————— 16 from django.forms import ValidationError 17 from django.shortcuts import render,redirect 18 # ————————28PerfectCRM實現King_admin編輯限制———————— 19 20 21 22 23 # ————————62PerfectCRM實現CRM講師講課記錄———————— 24 # 02班級表 25 class ClassListAdmin(BaseAdmin): 26 list_display = ['id', 'branch', 'course', 'class_type', 'semester', 'start_date', 'end_date'] # 顯示字段表頭 27 list_filter = ['branch', 'course', 'class_type'] # 過濾器(可以包含ManyToManyField) (注意加 逗號 , ) 28 filter_horizontal = ['teachers'] #復選框 29 site.register(models.ClassList,ClassListAdmin) #02班級表 30 31 # ————————62PerfectCRM實現CRM講師講課記錄———————— 32 33 34 35 36 #04客戶信息表 37 class CustomerAdmin(BaseAdmin):#定制Djanago admin 38 # ————————54PerfectCRM實現CRM客戶報名鏈接———————— 39 # list_display = ('id', 'qq', 'source', 'consultant', 'content', 'date') # 顯示字段表頭 40 list_display = ('id', 'qq', 'source', 'consultant', 'content', 'date','status','enroll') # 顯示字段表頭 41 # ————————54PerfectCRM實現CRM客戶報名鏈接———————— 42 # ————————11PerfectCRM實現King_admin分頁顯示條數———————— 43 list_per_page = 2 #分頁條數 # 默認分頁條數10 44 # ————————11PerfectCRM實現King_admin分頁顯示條數———————— 45 # ————————16PerfectCRM實現King_admin日期過濾———————— 46 # ————————15PerfectCRM實現King_admin多條件過濾———————— 47 # 過濾器(可以包含ManyToManyField) (注意加 逗號 , ) 48 # list_filter = ('source','consultant','consult_courses',) 49 list_filter = ('date','source','consultant','consult_courses',) 50 # ————————15PerfectCRM實現King_admin多條件過濾———————— 51 # ————————16PerfectCRM實現King_admin日期過濾———————— 52 # ————————18PerfectCRM實現King_admin搜索關鍵字———————— 53 #搜索(不能包含CharField)(注意加 逗號 , ) 54 search_fields = ('name','qq',) 55 # ————————18PerfectCRM實現King_admin搜索關鍵字———————— 56 # ————————26PerfectCRM實現King_admin自定義排序———————— 57 ordering = '-qq' #自定義排序,默認'-id' 58 # ————————26PerfectCRM實現King_admin自定義排序———————— 59 # ————————27PerfectCRM實現King_admin編輯復選框———————— 60 filter_horizontal = ('tags',) #復選框 61 # ————————27PerfectCRM實現King_admin編輯復選框———————— 62 # ————————33PerfectCRM實現King_admin編輯整張表限制———————— 63 readonly_table=True#默認表單不鎖定 64 # ————————33PerfectCRM實現King_admin編輯整張表限制———————— 65 66 # ————————55PerfectCRM實現CRM客戶報名狀態顏色變化———————— 67 colored_fields = { 68 'status':{'已報名':"rgba(145, 255, 0, 0.78)", 69 '未報名':"#ddd"},} 70 # ————————55PerfectCRM實現CRM客戶報名狀態顏色變化———————— 71 72 # ————————54PerfectCRM實現CRM客戶報名鏈接———————— 73 def enroll(self): 74 '''報名''' 75 print("customize field enroll",self) 76 link_name = "報名" 77 if self.instance.status == 0: 78 link_name = "報名新課程" 79 return '''<a target="_blank" class="btn-link" href="/bpm/customer/%s/enrollment/">點擊%s</a> ''' % (self.instance.id,link_name) 80 # url(r'^customer/(\d+)/enrollment/$', sales_views.enrollment, name="enrollment"), # 客戶招生#報名流程一 下一步 81 # target屬性用於表示所鏈接文件打開到的位置 #記住,“”內的文字只是表示一個對象的名子。 82 enroll.display_name = "報名鏈接" 83 # ————————54PerfectCRM實現CRM客戶報名鏈接———————— 84 85 86 87 # ————————24PerfectCRM實現King_admin自定義操作數據———————— 88 # from django.shortcuts import render 89 actions = ['test_actions',]#定制功能 #測試返回到一個新頁面 90 def test_actions(self,request,arg2):#對應的函數 #request類自己的請求 #arg2類的內容 91 return render(request,"king_admin/table_index.html") 92 test_actions.short_description = "測試顯示中文" 93 # ————————24PerfectCRM實現King_admin自定義操作數據———————— 94 95 # ————————28PerfectCRM實現King_admin編輯限制———————— 96 # ————————31PerfectCRM實現King_admin編輯多對多限制———————— 97 # readonly_fields = ('qq', 'consultant',) # 不可修改 98 readonly_fields = ('qq', 'consultant','tags',) # 不可修改 99 # ————————31PerfectCRM實現King_admin編輯多對多限制———————— 100 101 # ————————29PerfectCRM實現King_admin編輯自定義限制———————— 102 def default_form_validation(self,obj): 103 print('validation:制定的',obj.cleaned_data) 104 consult_course=obj.cleaned_data.get('content','')#自制驗證字段 105 if len(consult_course)<10: 106 return ValidationError(#添加錯誤信息 返回 107 ("該字段%(field)s 咨詢內容記錄不能少於10個字符"), 108 code='invalid', 109 params={'field':'content',}, 110 ) 111 # ————————29PerfectCRM實現King_admin編輯自定義限制———————— 112 113 # ————————28PerfectCRM實現King_admin編輯限制———————— 114 115 # ————————30PerfectCRM實現King_admin編輯自定義字段驗證———————— 116 def clean_name(self,obj,*args,**kwargs):#名稱驗證 單個 117 name=obj.cleaned_data['name'] 118 if not name: 119 obj.add_error('name','不能為空!') 120 return ValidationError(#添加錯誤信息 返回 121 ("%(field)s:該字段 不能為空"), 122 code='invalid', 123 params={'field':'name',}, 124 ) 125 elif len(name)<5: 126 obj.add_error('name','不能小於5個字符!') 127 #return ValidationError('',) 128 return ValidationError(#添加錯誤信息 返回 129 ("%(field)s:該字段 不能小於5個字符!"), 130 code='invalid', 131 params={'field':'name',}, 132 ) 133 # ————————30PerfectCRM實現King_admin編輯自定義字段驗證———————— 134 135 # ————————34PerfectCRM實現CRM自定義用戶———————— 136 #10賬號表 137 class UserProfileAdmin(BaseAdmin):#定制Djanago admin 138 list_display = ('id', 'email', 'name') # 顯示字段表頭 139 140 # ————————36PerfectCRM實現King_admin密碼修改———————— 141 readonly_fields = ('password',) # 不可修改,限制 142 143 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 144 # filter_horizontal = ('user_permissions','groups') #復選框 145 filter_horizontal = ('user_permissions', 'groups','roles') # 復選框 146 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 147 148 modelform_exclude_fields=['last_login']#排除#不顯示 #自增日期 #base_admin.py #forms.py 149 # ————————36PerfectCRM實現King_admin密碼修改———————— 150 151 site.register(models.UserProfile, UserProfileAdmin) 152 # ————————34PerfectCRM實現CRM自定義用戶———————— 153 154 # ————————05PerfectCRM實現King_admin注冊功能獲取內存———————— 155 # register(models.Customer,CustomerAdmin) 156 # register(models.CourseRecord) 157 site.register(models.Customer,CustomerAdmin) 158 # ————————58PerfectCRM實現king_admin批量生成上課記錄———————— 159 # site.register(models.CourseRecord) 160 # ————————58PerfectCRM實現king_admin批量生成上課記錄———————— 161 # ————————05PerfectCRM實現King_admin注冊功能獲取內存———————— 162 163 # ————————04PerfectCRM實現King_admin注冊功能———————— 164 165 166 # ————————56PerfectCRM實現CRM客戶報名繳費鏈接———————— 167 # 06學員報名信息表 168 class EnrollmentAdmin(BaseAdmin): # 定制Djanago admin 169 list_display = ('id', 'customer', 'enrolled_class', 'consultant', 'Pay_cost', 'date', 'payment') # 顯示字段表頭 170 171 # ————————58PerfectCRM實現king_admin批量生成上課記錄———————— 172 list_filter = ('enrolled_class','consultant', 'Pay_cost',) # 過濾器(可以包含ManyToManyField) (注意加 逗號 , ) 173 # ————————58PerfectCRM實現king_admin批量生成上課記錄———————— 174 175 colored_fields = { 176 'Pay_cost': {True: "rgba(145, 255, 0, 0.78)", 177 False: "#ddd"}, } 178 def payment(self): 179 link_name = "增加繳費" 180 if self.instance.Pay_cost == False: 181 link_name = "繳費" 182 return '''<a target="_blank" class="btn-link" href="/bpm/payment/%s/" >點擊%s</a> ''' % (self.instance.id, link_name) 183 # url(r'^payment/(\d+)/$', financial_views.payment, name="payment"), # 報名流程四 繳費 #財務 184 # target屬性用於表示所鏈接文件打開到的位置 #記住,“”內的文字只是表示一個對象的名子。 185 payment.display_name = "繳費鏈接" 186 site.register(models.Enrollment, EnrollmentAdmin) # 06學員報名信息表 187 # ————————56PerfectCRM實現CRM客戶報名繳費鏈接———————— 188 189 # ————————58PerfectCRM實現king_admin批量生成上課記錄———————— 190 # 07繳費記錄表 191 class PaymentAdmin(BaseAdmin): 192 list_display = ['id', 'customer', 'course', 'amount', 'consultant','date'] # 顯示字段表頭 193 list_filter = ('customer', 'course', 'consultant',) # 過濾器(可以包含ManyToManyField) (注意加 逗號 , ) 194 195 from django.shortcuts import render, HttpResponse, redirect 196 # 08每節課上課紀錄表 197 class CourseRecordAdmin(BaseAdmin): 198 list_display = ['id', 'from_class', 'day_num', 'teacher', 'has_homework', 'homework_title', 'homework_content','outline', 'date'] # 顯示字段表頭 199 list_filter = ('from_class', 'teacher', 'date') # 過濾器(可以包含ManyToManyField) (注意加 逗號 , ) 200 def initialize_studyrecords(self, request, queryset): # 制定功能 201 print('initialize_studyrecords', self, request, queryset) 202 if len(queryset) > 1: 203 return HttpResponse("同時只能選擇一個班級!") 204 print('獲取對應的學員', queryset[0].from_class.enrollment_set.all()) # _set反向查詢 205 new_obj_list = [] # 用於批量創建事務 #防止數據庫事物回滾 206 for enrll_obj in queryset[0].from_class.enrollment_set.all(): # 創建學習記錄 207 # models.StudyRecord.objects.get_or_create( #get_or_ #防止報錯 208 # student=enrll_obj,#對應學員 209 # course_record=queryset[0], 210 # attendance=0,#簽到狀態,默認簽到, 211 # score=0,#成績 212 # ) 213 214 # 防止數據庫事物回滾 #"""09學習紀錄""" 215 new_obj_list.append(models.StudyRecord( 216 student=enrll_obj, # 對應學員 217 course_record=queryset[0], # 班級#節課 218 attendance=0, # 簽到狀態,默認簽到, 219 score=0, # 成績 220 )) 221 try: 222 models.StudyRecord.objects.bulk_create(new_obj_list) # bulk_create批量創建數據庫事物 #統一最后保存 223 except Exception as e: 224 return HttpResponse('批量創建失敗,本節課可能有相應的上課記錄') 225 226 return redirect("/king_admin/crm/studyrecord/?course_record=%s" % queryset[0].id) # 學習記錄 #加上過濾 227 228 actions = ['initialize_studyrecords', ] 229 initialize_studyrecords.short_description = "創建班級本節上課記錄" # 顯示別名 230 # 09學習紀錄 231 class StudyRecordAdmin(BaseAdmin): 232 list_display = ['id', 'student', 'course_record', 'attendance', 'score', 'date'] # 顯示字段表頭 233 234 list_filter = ['course_record', 'attendance', 'score', 'student'] # 過濾器(可以包含ManyToManyField) (注意加 逗號 , ) 235 236 list_editable = ['score', 'attendance'] # 可編輯 #用於上課點名 批改成績 237 238 site.register(models.Payment, PaymentAdmin) # 07繳費記錄表 239 site.register(models.CourseRecord, CourseRecordAdmin) # 08每節課上課紀錄表 240 site.register(models.StudyRecord, StudyRecordAdmin) # 09學習紀錄 241 # ————————58PerfectCRM實現king_admin批量生成上課記錄———————— 242 243 244 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 245 # 11角色表 246 class RoleAdmin(BaseAdmin): 247 list_display = ['id', 'name'] # 顯示字段表頭 248 filter_horizontal = ['menus'] # 復選框 249 site.register(models.Role,RoleAdmin) #11角色表 250 251 # 13一層菜單名 252 class FirstLayerMenuAdmin(BaseAdmin): 253 list_display = ['id', 'name', 'url_type', 'url_name', 'order'] # 顯示字段表頭 254 site.register(models.FirstLayerMenu,FirstLayerMenuAdmin) #13一層菜單名 255 # 14二層菜單名 256 class SubMenuMenuAdmin(BaseAdmin): 257 list_display = ['id', 'name', 'url_type', 'url_name', 'order'] # 顯示字段表頭 258 site.register(models.SubMenu,SubMenuMenuAdmin) #14二層菜單名 259 # ————————72PerfectCRM實現CRM動態菜單和角色———————— 260 261 # ————————74PerfectCRM實現CRM權限和權限組限制訪問URL———————— 262 class GroupsAdmin(BaseAdmin): 263 list_display = ['id', 'name'] # 顯示字段表頭 264 filter_horizontal = ['permissions'] # 復選框 265 site.register(models.Groups,GroupsAdmin) #14二層菜單名 266 # ————————74PerfectCRM實現CRM權限和權限組限制訪問URL———————— 267 268 # ————————75PerfectCRM實現CRM擴展權限———————— 269 class PermissionsAdmin(BaseAdmin): 270 list_display = ['id', 'name','codename','dic_name'] # 顯示字段表頭 271 site.register(models.Permissions,PermissionsAdmin) #16擴展權限 272 # ————————75PerfectCRM實現CRM擴展權限————————

1 # permission.py 2 # ————————74PerfectCRM實現CRM權限和權限組限制URL———————— 3 from django.urls import resolve # resolve解析URL 4 from django.shortcuts import render,redirect,HttpResponse #頁面返回 5 from permissions.permission_list import perm_dic #權限字典 6 # ————————75PerfectCRM實現CRM擴展權限———————— 7 import json #字符串轉列表 8 from crm import models #數據庫查詢擴展的權限 9 from permissions.ECJ import * #擴展的自定義函數 10 # ————————75PerfectCRM實現CRM擴展權限———————— 11 def perm_check(*args,**kwargs): 12 print( '執行perm_check:', *args, **kwargs ) 13 request = args[0]# 14 # print(request) #<WSGIRequest: GET '/king_admin/crm/firstlayermenu/4/change/'> 15 16 resolve_url_obj = resolve(request.path)#反解URL路徑#獲取當前的URL# resolve解析URL#生成實例 17 print('反解URL路徑:',resolve_url_obj)#ResolverMatch(func=permissions.permission.inner, args=('crm', 'firstlayermenu', '4'), kwargs={}, url_name=table_change, app_names=[], namespaces=[]) 18 current_url_name = resolve_url_obj.url_name # 當前url的url_name 19 print('當前用戶:',request.user,'當前url的url_name:',current_url_name)#admin2 當前url的url_name: table_change 20 21 permission_list= request.user.user_permissions.values_list('codename') # 根據 登陸的ID 獲取 擁有的權限列表 22 print('擁有的權限列表',permission_list) 23 24 permission_group = request.user.groups.all().values_list('permissions__codename') # 根據 登陸的ID 獲取 擁有的組 25 print('擁有的權限組',permission_group) 26 27 match_key = None 28 match_results = [False,] #后面會覆蓋,加個False是為了讓all(match_results)不出錯 29 30 # ————————75PerfectCRM實現CRM擴展權限———————— 31 print('permission_list',perm_dic) #permission_list 32 models_dic = dict(models.Permissions.objects.values_list( 'codename', 'dic_name' ))#查詢數據庫 33 print( 'models_dic', models_dic ) 34 perm_dic.update(models_dic) #擴展權限字典 35 print( '擴展后的權限字典', perm_dic ) 36 # ————————75PerfectCRM實現CRM擴展權限———————— 37 38 for permission_key,permission_val in perm_dic.items():#從權限字典中取相關字段 #crm_table_index':['1','table_index','GET',[],{},], 39 # print('循環權限表',((permission_key),)) 40 if ((permission_key),) in permission_list or ((permission_key),) in permission_group:#權限列表是元組 41 # ————————75PerfectCRM實現CRM擴展權限———————— 42 if type( permission_val ).__name__ in ['str']: 43 permission_val = json.loads( permission_val ) # 字符串轉列表 44 # ————————75PerfectCRM實現CRM擴展權限———————— 45 46 per_url_name = permission_val[0] #URL 47 per_method = permission_val[1] #GET #POST #請求方法 48 perm_args = permission_val[2] # 列表參數 49 perm_kwargs = permission_val[3]# 字典參數 50 51 # ————————75PerfectCRM實現CRM擴展權限———————— 52 # custom_perm_func = None if len(permission_val) == 4 else permission_val[4] #url判斷 #自定義權限鈎子 53 if len( permission_val ) == 4 : 54 custom_perm_func = None 55 else: 56 if type( permission_val[4] ).__name__ in ['str']: 57 custom_perm_func = globals().get( permission_val[4] ) # url判斷 #自定義權限鈎子 58 else: 59 custom_perm_func = permission_val[4] 60 # ————————75PerfectCRM實現CRM擴展權限———————— 61 62 # 'crm_can_access_my_clients':['table_list','GET',[],{'perm_check':33,'arg2':'test'}, custom_perm_logic.only_view_own_customers], 63 # print('URL:',per_url_name,'請求方法:',per_method,'列表參數:',perm_args,'字典參數:',perm_kwargs,'自定義權限鈎子:',custom_perm_func) 64 65 66 if per_url_name == current_url_name: #權限字典的 URL ==當前請求的url #crm_table_index':['URL','請求方法',[列表參數],{字典參數},], 67 if per_method == request.method: #權限字典的 請求方法 == 當前請求的方法 #crm_table_index':['URL','請求方法',[列表參數],{字典參數},], 68 #逐個匹配參數,看每個參數時候都能對應的上。 69 args_matched = False #參數匹配 #僅供參數 70 for item in perm_args: #循環列表參數 #crm_table_index':['URL','請求方法',[列表參數],{字典參數},], 71 request_method_func = getattr(request,per_method) #反射 #請求方法 #GET #POST 72 if request_method_func.get(item,None):# 如果request字典中有此參數 73 args_matched = True 74 else: 75 print("參數不匹配......") 76 args_matched = False 77 break # 有一個參數不能匹配成功,則判定為假,退出該循環。 78 else: 79 args_matched = True #沒有執行 break 表示 列表匹配成功 #防止列表沒有使用參數時出錯 80 81 #匹配有特定值的參數 82 kwargs_matched = False 83 for k,v in perm_kwargs.items(): #循環字典參數#crm_table_index':['URL','請求方法',[列表參數],{字典參數},], 84 request_method_func = getattr(request, per_method) #反射 #請求方法 #GET #POST 85 arg_val = request_method_func.get(k, None) # request字典中有此參數 86 print("perm kwargs check:",arg_val,type(arg_val),v,type(v)) 87 if arg_val == str(v): #匹配上了特定的參數 及對應的 參數值, 比如,需要request 對象里必須有一個叫 user_id=3的參數 88 kwargs_matched = True 89 else: 90 kwargs_matched = False 91 break # 有一個參數不能匹配成功,則判定為假,退出該循環。 92 else: 93 kwargs_matched = True 94 95 96 #自定義權限鈎子 97 perm_func_matched = False 98 if custom_perm_func: #如果有定義 99 if custom_perm_func(request,args,kwargs):#def only_view_own_customers(request,*args,**kwargs): 100 perm_func_matched = True 101 else: 102 perm_func_matched = False #使整條權限失效 103 print('自定義權限鈎子沒有通過',perm_func_matched) 104 else: #沒有定義權限鈎子,所以默認通過 105 perm_func_matched = True 106 107 match_results = [args_matched,kwargs_matched,perm_func_matched] #列表 108 print("匹配結果: ", match_results) # [True, True, True] 109 if all(match_results): #都匹配上了 #都返回 True 110 match_key = permission_key # 給 match_key = None 賦值 111 break #跳出大循環 112 113 if all(match_results): #如果都匹配成功 #'crm_table_index':['table_index','GET',[],{},], 114 app_name, *per_name = match_key.split('_') #先給app_name賦一個值,其他的值都給*per_name 'crm_table_index': 115 print("權限名:",match_key,'權限:',match_results)#crm_010902_only_view_CourseRecord_POST [True, True, True] 116 print('分割:',app_name, *per_name) # crm 010902 only view CourseRecord POST 117 perm_obj = '%s.%s' % (app_name,match_key)#'crm.table_index' # url(r'^(\w+)/$', views.table_index, name='table_index'), # 單個具體app頁面 118 print("生成權限:",perm_obj) #crm.crm_010902_only_view_CourseRecord_POST 119 if request.user.has_perm(perm_obj): 120 print('當前用戶有此權限') 121 return True 122 else: 123 print('當前用戶沒有該權限') 124 return False 125 else: 126 print("未匹配到權限項,當前用戶無權限") 127 128 def check_permission(func): 129 print('權限func',func)#權限func <function table_data_list at 0x030636A8> #循環 URL name 130 def inner(*args,**kwargs): 131 print('開始權限匹配:',type(args)) 132 request = args[0]#請求第一個 133 print('判斷登陸情況:') 134 if request.user.id == None: 135 print('未登陸') 136 return redirect( '/gbacc/gbacc_login/' )#返回登陸頁面 137 else: 138 if request.user.is_superuser == True: 139 print('超級管理員') 140 return func( *args, **kwargs ) #直接返回 真 141 print( '已登陸,判斷有perm_check(*args,**kwargs)去執行' ) 142 if not perm_check(*args,**kwargs): #如果返回不為真 #沒權限 143 print('#沒權限',perm_check(*args,**kwargs)) 144 request = args[0] 145 return HttpResponse('你沒有這個權限') 146 print('有權限',func(*args,**kwargs)) #<HttpResponse status_code=200, "text/html; charset=utf-8"> 147 return func(*args,**kwargs) 148 print('inner',inner) 149 return inner #返回 真或假 150 # ————————74PerfectCRM實現CRM權限和權限組限制URL————————

1 # ECJ.py 2 # ————————75PerfectCRM實現CRM擴展權限———————— 3 import re #正則 4 5 #070101_查看自己的客戶表_GET 6 def view_own_Customer(request,*args,**kwargs): 7 url_path = request.path #獲取URL 路徑 8 url_list=re.findall('(\w+)',url_path) #正者表達式 獲取參數 9 url_model_name= url_list[2] #字符串 10 model_name = 'customer'#字符串 11 if url_model_name==model_name: #防止其他表通過權限 12 consultant_id = request.GET.get('consultant') #過濾條件 &consultant=7 13 if consultant_id: 14 consultant_id = int(consultant_id) #轉換成 數字 15 if consultant_id == request.user.id: # 賬號表 的ID 等於 #當前登陸的ID 16 return True 17 else: 18 return False 19 else: 20 return False 21 22 #070103_修改自己的客戶表_GET 23 #070105_刪除自己的客戶表_GET 24 def change_own_Customer(request,*args,**kwargs): 25 url_path = request.path #獲取URL 路徑 26 url_list=re.findall('(\w+)',url_path) #正者表達式 獲取參數 27 url_model_name= url_list[2] 28 url_parameter =int(url_list[3]) 29 model_name = 'customer' 30 if url_model_name==model_name: #防止其他表通過權限 31 if request.user.id: #如果有ID 32 list= request.user.customer_set.all()#獲取ID 的客戶表 33 list_id=[] 34 for obtain in list:#循環客戶表ID 35 results=obtain.id 36 list_id.append(results)#生成列表 37 if url_parameter in list_id: #對比URL參數 在不在 客戶表ID里 38 return True 39 else: 40 return False 41 else: 42 return False 43 44 # ————————75PerfectCRM實現CRM擴展權限————————
如果感覺本章博客對您有幫助,請盡情打賞吧!