Django项目:CRM(客户关系管理系统)--58--48PerfectCRM实现CRM客户报名流程学生合同

 

 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     url(r'^customer/(\d+)/enrollment/$', sales_views.enrollment, name="enrollment"),#客户招生#报名流程一 下一步
 8 
 9     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
10     url(r'^customer/registration/(\d+)/$', sales_views.stu_registration, name="stu_registration"),  # 报名流程二 学员签同合
11     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
12 ]
13 # ————————47PerfectCRM实现CRM客户报名流程————————
# sales_urls.py

 

 

 

 

 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 #发送邮件的功能 #验证码#密码
15 class stmp() :
16     def __init__(self):
17         self.emaillist=[]  #发送给谁
18         self.code=None    #验证码#密码
19     def stmps(self,request,email,msg_mail): #传参数#页面,session #邮箱,发送给谁 #内容
20         self.emaillist.append(email) #将邮箱地址添加到调用Django发送邮件功能
21         # ——————生成验证码——————
22         _letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
23         _upper_cases = _letter_cases.upper()  # 大写字母
24         _numbers = ''.join(map(str, range(3, 10)))  # 数字
25         chars = ''.join((_letter_cases, _upper_cases, _numbers))  # 变成一条字符串
26         list = random.sample(chars, 4)  # 从一条字符串随机选4个字符变成列表
27         self.code = ''.join(list)  # 列表变字符串
28         # ——————生成验证码——————
29         # ——————调用Django发送邮件——————
30         title= 'PerfectCRM项目自动邮件:%s'%self.code   # 邮件标题#防止一样的内容被邮箱屏蔽
31         send_mail(title,  # 邮件标题
32                   msg_mail,  # 验证码内容
33                   'perfectcrm@sina.cn',  # 发送的邮箱  #根据情况重新配置
34                   self.emaillist,  # 接受的邮箱
35                   fail_silently=False,  # 静默,抛出异常
36                   )
37         print('发送邮件成功!没收到要换标题!检查发送邮箱的配置!')
38         # ——————调用Django发送邮件——————
39 
40 # ————————47PerfectCRM实现CRM客户报名流程————————
41 # ————————47PerfectCRM实现CRM客户报名流程————————
42 
43 #报名填写 销售
44 @login_required # 登陆后页面才能访问
45 def enrollment(request,customer_id):
46     msgs={} #错误信息
47     customer_obj=models.Customer.objects.get(id=customer_id)#取到客户信息记录 #返回到页面#报名人
48     consultant_obj=models.UserProfile.objects.get(id=request.user.id)#报名课程顾问
49 
50     stmp_mail = {}  #邮件发送成功
51     stmpemail = stmp() #实例化发送邮件的功能
52     email = request.POST.get('email')  # 让页面POST提交的值,在页面GET后仍然存在显示
53     if request.method=="POST":
54         enroll_form= bpm_forms.EnrollmentForm(request.POST)#获取数据
55         if enroll_form.is_valid():#表单验证
56             msg = "http://127.0.0.1:8000/bpm/customer/registration/{enroll_obj_id}/"
57             try:
58                 enroll_form.cleaned_data['customer']=customer_obj#添加学员对象 记录 #报名人
59                 enroll_form.cleaned_data['consultant'] = consultant_obj#报名课程顾问
60                 enroll_obj=models.Enrollment.objects.create(**enroll_form.cleaned_data)#创建记录
61                 msgs['msg']=msg.format(enroll_obj_id=enroll_obj.id)#报名记录对应的id
62             except IntegrityError as e:
63                 #取到这条记录
64                 enroll_obj=models.Enrollment.objects.get(customer_id=customer_obj.id,
65                                                          enrolled_class_id=enroll_form.cleaned_data['enrolled_class'].id)
66                 enroll_form.add_error('__all__','记录已经存在,不能重复创建!')
67                 msgs['msg']=msg.format(enroll_obj_id=enroll_obj.id)#报名记录对应的id
68             if email:
69                 msg_mail = "http://127.0.0.1:8000/bpm/customer/registration/%s/"%enroll_obj.id
70                 stmpemail.stmps(request, email,msg_mail)  # 发送邮件
71                 stmp_mail['ok'] = "邮件已发送成功!"
72 
73     else:
74         enroll_form= bpm_forms.EnrollmentForm()#modelform表单
75     return render(request, 'bpm_sales/enrollment.html', locals())
76 # ————————47PerfectCRM实现CRM客户报名流程————————
77 
78 
79 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
80 #学员合同签定
81 def stu_registration(request,enroll_id):
82     enroll_obj=models.Enrollment.objects.get(id=enroll_id)#获取报名记录
83     customer_form= bpm_forms.CustomerForm(instance=enroll_obj.customer)#生成表单
84     return render(request,'bpm_sales/stu_registration.html',locals())
85 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
# sales_views.py

 

 

 

 

 

 1 # forms.py
 2 # ————————47PerfectCRM实现CRM客户报名流程————————
 3 from crm import models  #数据库
 4 from django.forms import ModelForm  #继承forms自定制
 5 #报名 销售填写
 6 class EnrollmentForm(ModelForm):
 7     def __new__(cls, *args, **kwargs):
 8         for field_name,field_obj in cls.base_fields.items():
 9             field_obj.widget.attrs['class'] = 'form-control'## 前端的样式
10         return ModelForm.__new__(cls)
11     class Meta:
12         model= models.Enrollment
13         fields= ['enrolled_class']
14 # ————————47PerfectCRM实现CRM客户报名流程————————
15 
16 
17 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
18 #报名学员填 写
19 class CustomerForm(ModelForm):
20     def __new__(cls, *args, **kwargs):
21         for field_name,field_obj in cls.base_fields.items():
22             field_obj.widget.attrs['class'] = 'form-control'## 前端的样式
23             if field_name in cls.Meta.readonly_fields:#如果不可修改
24                 field_obj.widget.attrs['disabled'] = True## 前端的样式 灰色
25         return ModelForm.__new__(cls)
26 
27     class Meta:
28         model=models.Customer#客户表
29         fields='__all__'
30         exclude=['tags','content','memo','status','referral_from','consult_courses']#排除,不显示
31         readonly_fields=['qq','consultant','source']#不可修改
32 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
# forms.py

 

 

 

 

 1 {#stu_registration.html#}
 2 {## ————————48PerfectCRM实现CRM客户报名流程学生合同————————#}
 3 {% extends 'bpm_master/bpm_sample.html' %}
 4 {% load bpm_tags %}
 5 {% block right-container-content %} {#自定义内容开始 右边页面内容#}
 6     <div class="container col-lg-7 col-md-offset-2">
 7         <div class="panel panel-warning">
 8             <div class=" panel-heading">
 9                 <h3 class="panel-title container">报名入学|信息填写</h3>
10             </div>
11             <div class="panel-body ">                           <!--返回提交函数-->
12                 <form method="post" class="form-horizontal" role="form">{% csrf_token %}
13                     {% for foo in customer_form %}
14                         <div class="form-group">
15                             <label for="inputEmail3" class="col-sm-2 control-label">{{ foo.label }}</label>
16                             <div class="col-sm-8">
17                                 {{ foo }}
18                             </div>
19                         </div>
20                     {% endfor %}
21                     <hr>
22                     {#返回06学员报名信息表的数据#}
23                     <div class="form-group">
24                         <label for="inputEmail3" class="col-sm-2 control-label">所报班级</label>
25                         <div class="col-sm-8">
26                             {{ enroll_obj.enrolled_class }}
27                         </div>
28                     </div>
29                     <div class="form-group">
30                         <label for="inputEmail3" class="col-sm-2 control-label">课程费用</label>
31                         <div class="col-sm-8">
32                             {{ enroll_obj.enrolled_class.course.price }}
33                         </div>
34                     </div>
35                     <div class="form-group">
36                         <label for="inputEmail3" class="col-sm-2 control-label">开课日期</label>
37                         <div class="col-sm-8">
38                             {{ enroll_obj.enrolled_class.start_date }}
39                         </div>
40                     </div>
41 
42                     <div class="form-group">
43                         <label for="inputEmail3" class="col-sm-2 control-label">合同</label>
44                         <div class="col-sm-10">
45                             <div style="width: 550px">
46                                 <pre style="height: 300px">{% render_enrolled_contract enroll_obj %}  </pre> <!--tgs-->
47                             </div>
48 
49                         </div>
50                     </div>
51                     <div class="form-group">
52                         <div class="col-sm-12">
53                             <input type="checkbox" value="{{ enroll_obj.contract_agreed }}" name="contract_agreed"
54                                    checked>
55                             我已经认真阅读完协议并接受所有条款
56                         </div>
57                     </div>
58                     <div class="text-center">
59                         <input type="submit" class="btn btn-info" value="提交">
60                     </div>
61                 </form>
62             </div>
63             <div class="panel-footer">
64                 <input type="button" class="btn btn-danger right" value="关闭" onclick="CloseWebPage()">
65             </div>
66         </div>
67     </div>
68 {% endblock %}
69 
70 {% block js %}
71     <script>
72         function CloseWebPage() {
73             if (confirm("您确定要关闭本页吗?")) {
74                 window.opener = null;
75                 window.open('', '_self');
76                 window.close();
77             }
78             else {
79             }
80         }
81     </script>
82 {% endblock %}
83 {## ————————48PerfectCRM实现CRM客户报名流程学生合同————————#}
{#stu_registration.html#}

 

 

 

 1 # bpm_tags.py
 2 
 3 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
 4 from django import template
 5 register = template.Library()    #模板库
 6 
 7 #合同格式
 8 @register.simple_tag
 9 def render_enrolled_contract(enroll_obj):#合同格式
10     if enroll_obj.enrolled_class.contract.template:
11         return enroll_obj.enrolled_class.contract.template.format(course_name=enroll_obj.enrolled_class,stu_name=enroll_obj.customer.name)
12     else:
13         return ''
14 
15 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
16 
17 # bpm_tags.py
# bpm_tags.py

 

 

  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 MIDDLEWARE = [
 61     'django.middleware.security.SecurityMiddleware',
 62     'django.contrib.sessions.middleware.SessionMiddleware',
 63     'django.middleware.common.CommonMiddleware',
 64     'django.middleware.csrf.CsrfViewMiddleware',
 65     'django.contrib.auth.middleware.AuthenticationMiddleware',
 66     'django.contrib.messages.middleware.MessageMiddleware',
 67     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 68 ]
 69 
 70 ROOT_URLCONF = 'PerfectCRM.urls'
 71 
 72 TEMPLATES = [
 73     {
 74         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 75 # ————————02PerfectCRM创建ADMIN页面————————
 76         'DIRS': [os.path.join(BASE_DIR, 'templates'),
 77                   os.path.join(BASE_DIR, 'king_admin/king_templates'),
 78 
 79 # ————————03PerfectCRM创建基本数据————————
 80                   os.path.join(BASE_DIR, 'DBadd/DBadd_templates'),
 81 # ————————03PerfectCRM创建基本数据————————
 82                 # ————————38PerfectCRM实现全局账号登录注销————————
 83                   os.path.join(BASE_DIR, 'gbacc/gbacc_templates'),
 84                 # ————————38PerfectCRM实现全局账号登录注销————————
 85 
 86                 # ————————47PerfectCRM实现CRM客户报名流程————————
 87                 os.path.join(BASE_DIR, 'bpm/bpm_templates'), ]
 88                 # ————————47PerfectCRM实现CRM客户报名流程————————
 89 
 90 ,
 91 # ————————02PerfectCRM创建ADMIN页面————————
 92         'APP_DIRS': True,
 93         'OPTIONS': {
 94             'context_processors': [
 95                 'django.template.context_processors.debug',
 96                 'django.template.context_processors.request',
 97                 'django.contrib.auth.context_processors.auth',
 98                 'django.contrib.messages.context_processors.messages',
 99             ],
100         },
101     },
102 ]
103 
104 WSGI_APPLICATION = 'PerfectCRM.wsgi.application'
105 
106 
107 # Database
108 # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
109 
110 DATABASES = {
111     'default': {
112         'ENGINE': 'django.db.backends.sqlite3',
113         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
114     }
115 }
116 
117 
118 # Password validation
119 # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
120 
121 AUTH_PASSWORD_VALIDATORS = [
122     {
123         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
124     },
125     {
126         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
127     },
128     {
129         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
130     },
131     {
132         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
133     },
134 ]
135 
136 
137 # Internationalization
138 # https://docs.djangoproject.com/en/2.0/topics/i18n/
139 
140 # ————————01PerfectCRM基本配置ADMIN————————
141 #LANGUAGE_CODE = 'en-us'
142 
143 #英文转中文方法
144 LANGUAGE_CODE = 'zh-Hans'
145 # ————————01PerfectCRM基本配置ADMIN————————
146 
147 TIME_ZONE = 'UTC'
148 
149 USE_I18N = True
150 
151 USE_L10N = True
152 
153 USE_TZ = True
154 
155 
156 # Static files (CSS, JavaScript, Images)
157 # https://docs.djangoproject.com/en/2.0/howto/static-files/
158 
159 STATIC_URL = '/static/'
160 
161 # ————————01PerfectCRM基本配置ADMIN————————
162 STATICFILES_DIRS = [os.path.join(BASE_DIR,'king_admin/static'),
163 # ————————01PerfectCRM基本配置ADMIN————————
164                     # ————————38PerfectCRM实现全局账号登录注销————————
165                     os.path.join(BASE_DIR, 'gbacc/static'),
166                     # ————————38PerfectCRM实现全局账号登录注销————————
167                     
168                     # ————————47PerfectCRM实现CRM客户报名流程————————
169                     os.path.join(BASE_DIR, 'bpm/static'),]
170                     # ————————47PerfectCRM实现CRM客户报名流程————————
171 
172 
173 # ————————34PerfectCRM实现CRM自定义用户————————
174 AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单
175 # ————————34PerfectCRM实现CRM自定义用户————————
176 
177 
178 
179 # ————————44PerfectCRM实现账号快速注册登陆————————
180 # send e-mail
181 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'  #email后端
182 EMAIL_USE_TLS = False   #是否使用TLS安全传输协议
183 EMAIL_USE_SSL = True    #是否使用SSL加密,qq企业邮箱要求使用
184 EMAIL_HOST = 'smtp.sina.cn'   #发送邮件的邮箱 的 SMTP服务器       #根据情况重新配置
185 EMAIL_PORT = 465                 #发件箱的SMTP服务器端口 #一般不需要修改465
186 EMAIL_HOST_USER = 'perfectcrm@sina.cn'    #发送邮件的邮箱账号     #根据情况重新配置  #perfectcrm@sina.cn   pydjango@sina.cn
187 EMAIL_HOST_PASSWORD = 'admin123456'         #发送邮件的邮箱密码    #根据情况重新配置
188 
189 # ————————44PerfectCRM实现账号快速注册登陆————————
190 
191 
192 # ————————46PerfectCRM实现登陆后页面才能访问————————
193 LOGIN_URL = '/gbacc/gbacc_login/'# login_url 配置      #默认 /accounts/login/  #注意: / (绝对路径)
194 # ————————46PerfectCRM实现登陆后页面才能访问————————
# settings.py

 

 

 

 

 

 

 

  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 
 85     source_choices = ( #客户渠道来源 (内存生成)
 86                       (0,'转介绍'),
 87                       (1,'QQ群'),
 88                       (2,'官网'),
 89                       (3,'百度推广'),
 90                       (4,'51CTO'),
 91                       (5,'知乎'),
 92                       (6,'市场推广'),)
 93     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
 94     source = models.SmallIntegerField(choices=source_choices)#客户渠道来源
 95 
 96     #CharField定长文本#verbose_name是Admin中显示的字段名称#名字最长64 # Django可空 #数据库可以为空
 97     referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True) #来自谁介绍的
 98 
 99     #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
100     consult_courses = models.ForeignKey("Course",verbose_name="咨询课程", on_delete=models.CASCADE) #关联到 课程表
101 
102     content= models.TextField(verbose_name="咨询详情") #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
103 
104     #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。
105     tags = models.ManyToManyField("Tag",blank=True)#多对多关联到 标签表
106 
107     #ForeignKey就是表与表之间的某种约定的关系  #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
108     consultant = models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到  账号表
109 
110     memo = models.TextField(blank=True,null=True)#备注#TextField无限制长度的文本#Django可空#数据库可以为空
111 
112     #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
113     date =  models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
114 
115     def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
116         return self.qq  #返回 #QQ号
117 
118     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
119         verbose_name_plural =  "04客户表" #verbose_name_plural给你的模型类起一个更可读的名字
120 
121 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
122 #合同模版
123 class ContractTemplate(models.Model):
124     name=models.CharField('合同名称',max_length=64,unique=True)
125     template=models.TextField()
126 
127     def __str__(self):
128         return self.name
129     class Meta:
130         verbose_name_plural='合同表'
131 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
132 
133 
134 """05客户跟进表"""
135 class CustomerFollowUp(models.Model):
136 
137     #ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
138     customer = models.ForeignKey("Customer", on_delete=models.CASCADE)#客户名 #关联到  客户信息表
139 
140     content = models.TextField(verbose_name="跟进内容")#跟进的内容#TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
141 
142     #ForeignKey就是表与表之间的某种约定的关系  #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
143     consultant =models.ForeignKey("UserProfile", on_delete=models.CASCADE) #关联到  账号表
144 
145     intention_choices =(  #报名状态
146                         (0,'2周内报名'),
147                         (1,'1个月内报名'),
148                         (2,'近期无报名计划'),
149                         (3,'已在其它机构报名'),
150                         (4,'已报名'),
151                         (5,'已拉黑'),)
152     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
153     intention=models.SmallIntegerField(choices=intention_choices) #报名状态
154 
155     #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
156     date =  models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
157 
158     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
159         return "<%s:%s>" %(self.customer.qq,self.intention) #返回#格式化字符串#跨表里的QQ号#报名状态
160     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
161         verbose_name_plural =  "05客户跟进表"#verbose_name_plural给你的模型类起一个更可读的名字
162 
163 """06学员报名信息表"""
164 class Enrollment(models.Model):
165     # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
166     customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字 #关联到  客户信息表
167     enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级",on_delete=models.CASCADE)#关联到  班级表
168     consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问",on_delete=models.CASCADE) #关联到  账号表
169 
170     #BooleanField布尔值类型#default=False默认(True)不允许出现空字符#verbose_name是Admin中显示的字段名称
171     contract_agreed = models.BooleanField(default=False,verbose_name="学员已经同意合同")#学员看合同
172     contract_approved = models.BooleanField(default=False,verbose_name="合同已经审核") #谁审核
173 
174     # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
175     date = models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
176 
177     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
178         return "%s %s" %(self.customer,self.enrolled_class)#返回#格式化字符串#学员名字#所报班级
179     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
180         unique_together =  ("customer","enrolled_class")#联合索引
181         verbose_name_plural =  "06学员报名信息表"#verbose_name_plural给你的模型类起一个更可读的名字
182 
183 """07缴费记录表"""
184 class Payment(models.Model):
185     #ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
186     customer = models.ForeignKey("Customer",on_delete=models.CASCADE)#学员名字        关联到  客户信息表
187     course = models.ForeignKey("Course",verbose_name="所报课程",on_delete=models.CASCADE)#关联到  课程表
188 
189     #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称#默认值=500
190     amount = models.PositiveIntegerField(verbose_name="数额",default=500)#缴费数额
191 
192     #ForeignKey就是表与表之间的某种约定的关系#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
193     consultant = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#缴费给谁 关联到  账号表
194 
195     #DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
196     date=models.DateTimeField(auto_now_add=True)#创建时间(数据库自增)
197 
198     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
199         return "%s %s" %(self.customer,self.amount)#返回#格式化字符串#学员名字#缴费数额
200     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
201         verbose_name_plural = "07缴费记录表"#verbose_name_plural给你的模型类起一个更可读的名字
202 
203 """08每节课上课纪录表"""
204 class CourseRecord(models.Model):
205     # ForeignKey就是表与表之间的某种约定的关系#verbose_name是Admin中显示的字段名称 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
206     from_class = models.ForeignKey("ClassList",verbose_name="班级",on_delete=models.CASCADE) #那个班级
207 
208     #PositiveSmallIntegerField正小整数 0 ~ 32767 #verbose_name是Admin中显示的字段名称
209     day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)") #第几节课
210 
211     # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
212     teacher = models.ForeignKey("UserProfile",on_delete=models.CASCADE)#老师是谁    关联到    账号表
213 
214     #BooleanField布尔值类型#default=True默认(True)不允许出现空字符
215     has_homework = models.BooleanField(default=True) #有没有作业
216 
217     # CharField定长文本#名字最长128#Django可空#数据库可以为空
218     homework_title = models.CharField(max_length=128,blank=True,null=True) #作业标题
219 
220     #TextField无限制长度的文本#Django可空#数据库可以为空
221     homework_content = models.TextField(blank=True,null=True) #作业内容
222 
223     #TextField无限制长度的文本#verbose_name是Admin中显示的字段名称
224     outline =models.TextField(verbose_name="本节课程大纲") #课程主要讲什么
225 
226     # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
227     date = models.DateField(auto_now_add=True)#创建时间(数据库自增)
228 
229     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
230         return " %s:%s" %(self.from_class,self.day_num)#返回#格式化字符串#班级#第几节(天)
231     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
232         unique_together = ("from_class","day_num") #联合索引
233         verbose_name_plural = "08每节课上课纪录表" #verbose_name_plural给你的模型类起一个更可读的名字
234 
235 """09学习纪录"""
236 class StudyRecord(models.Model):
237     # ForeignKey就是表与表之间的某种约定的关系 #CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
238     student = models.ForeignKey("Enrollment",on_delete=models.CASCADE)#学生名字   关联到    学员报名信息表
239     course_record = models.ForeignKey("CourseRecord",on_delete=models.CASCADE)#开课记录   # 关联到    每节课上课纪录表
240 
241     attendance_choices = (# 本节课上课状态记录
242                             (0,"已签到"),
243                             (1,"迟到"),
244                             (2,"缺勤"),
245                             (3,"早退"),)
246     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
247     attendance = models.SmallIntegerField(choices=attendance_choices) # 本节课上课状态记录
248 
249     score_choices = (#学习成绩
250                      (100,"A+"),
251                      (90,"A"),
252                      (85,"B+"),
253                      (80,"B"),
254                      (75,"B-"),
255                      (70,"C+"),
256                      (65,"C"),
257                      (40,"C-"),
258                      (-20,"D"),
259                      (-50,"COPY"),
260                      (0,"N/A"),)
261     #PositiveSmallIntegerField正小整数 0 ~ 32767(省空间)#choices是Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
262     score = models.SmallIntegerField(choices=score_choices) #学习成绩
263 
264     memo = models.TextField(blank=True,null=True)#TextField无限制长度的文本#Django可空#数据库可以为空
265 
266     # DateTimeField日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] #auto_now_add创建时间(只读)
267     date = models.DateField(auto_now_add=True)#创建时间(数据库自增)
268 
269     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
270         return "%s %s %s" % (self.student, self.course_record, self.score)#返回#格式化字符串#学生名字#开课记录#学习成绩
271     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
272         unique_together = ('student','course_record')#联合索引#学生名字#开课记录
273         verbose_name_plural =  "09学习纪录"#verbose_name_plural给你的模型类起一个更可读的名字
274 
275 # ————————34PerfectCRM实现CRM自定义用户————————
276 # """10账号表"""
277 # class UserProfile(models.Model):
278 #     from django.contrib.auth.models import User  # 使用django内置的用户表
279 #
280 #     #OneToOneField一对一  #User是django Admin里的账号表#CASCADE从父表删除或更新且自动删除或更新子表中匹配的行。
281 #     user = models.OneToOneField(User,on_delete=models.CASCADE)# 用户名 #创建外键,关联django用户表
282 #
283 #     name = models.CharField(max_length=32) #账号名(扩展用户字段)#CharField定长文本
284 #
285 #     #ManyToManyField多对多和外键工作方式相同,只不过我们处理的是QuerySet而不是模型实例。#Django可空
286 #     roles = models.ManyToManyField("Role",blank=True) #角色(权限)   # 双向一对多==多对多
287 #
288 #     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
289 #         return self.name #返回 #账号名
290 #     class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
291 #         verbose_name_plural = "10账号表"#verbose_name_plural给你的模型类起一个更可读的名字
292 # ————————34PerfectCRM实现CRM自定义用户————————
293 
294 # ————————34PerfectCRM实现CRM自定义用户————————
295 #10账号表,创建用户和超级用户
296 from django.contrib.auth.models import BaseUserManager
297 class UserProfileManager(BaseUserManager):
298     def create_user(self, email, name, password=None):
299         """
300       创建并保存一个用户用给定的邮件,日期
301       出生和密码。
302         """
303         if not email:#没有email 报错
304             raise ValueError('用户必须有一个电子邮件地址')
305 
306         user = self.model(
307             email=self.normalize_email(email),#验证邮箱格式
308             name=name,
309         )
310         user.set_password(password)#加密
311         user.is_active = True
312         user.save(using=self._db)
313         return user
314     def create_superuser(self, email, name, password):
315         """
316       创建并保存一个超级用户具有给定邮件,日期
317       出生和密码。
318         """
319         user = self.create_user(email,
320             password=password,
321             name=name
322         )
323         user.is_active = True
324         user.is_superuser = True
325         user.save(using=self._db)
326         return user
327 
328 """10账号表"""
329 """
330 
331 #删除数据库
332 
333 #调用objects = UserProfileManager()#创建账号 #关联这个函数
334 
335 #运行 Terminal
336 #    生成 数据表
337 #    python manage.py makemigrations
338 #   数据表 迁移
339 #    python manage.py migrate
340 Django Admin里账号密码重置方法
341 #运行 Terminal  
342 python manage.py createsuperuser
343 
344 Email address:          admin@qq.com
345 用户名 :                 admin
346 Password:               admin123456
347 Password (again):       admin123456
348 """
349 from django.contrib.auth.models import AbstractBaseUser
350 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
351 from django.utils.translation import ugettext_lazy as _  # 语言国际化
352 from django.utils.safestring import mark_safe
353 from django.contrib.auth.models import PermissionsMixin
354 # class UserProfile(AbstractBaseUser):
355 class UserProfile(AbstractBaseUser,PermissionsMixin):
356 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
357     email=models.EmailField(
358         verbose_name='邮箱账号',
359         max_length=255,
360         unique=True#唯一  #登陆账号
361     )
362     name=models.CharField(max_length=32,verbose_name='用户名')
363 
364     # ————————35PerfectCRM实现CRM重写Admin密码修改————————
365     password = models.CharField(_('password'), max_length=128, help_text=mark_safe('''<a href=\"../password/\">修改密码</a>'''))
366     # ————————35PerfectCRM实现CRM重写Admin密码修改————————
367 
368     is_active = models.BooleanField(default=True,verbose_name='合法账号')#权限#合法账号
369     is_superuser = models.BooleanField(default=False,verbose_name='超级账号') #超级账号
370     objects = UserProfileManager()#创建账号 #关联这个函数
371     USERNAME_FIELD ='email'#指定做为  #登陆账号
372     REQUIRED_FIELDS = ['name']#必填字段
373     def get_full_name(self):
374         return self.email
375     def get_short_name(self):
376         #用户确认的电子邮件地址
377         return self.email
378     def __str__(self):
379         return self.name
380     def has_perm(self,perm,obj=None):
381         #指明用户是否被认为活跃的。以反选代替删除帐号。
382         #最简单的可能的答案:是的,总是
383         return True   #有效 账号
384     def has_module_perms(self, app_label):
385         #指明用户是否可以登录到这个管理站点。
386         # 最简单的可能的答案:是的,总是
387         return True #职员状态
388     @property
389     def is_staff(self):
390         '''“用户的员工吗?”'''
391         #最简单的可能的答案:所有管理员都是员工
392         return self.is_superuser#是不是超级用户状态
393 # AUTH_USER_MODEL = 'crm.UserProfile'#使用自定的admin 表单   #settings.py
394 # ————————34PerfectCRM实现CRM自定义用户————————
395 
396 """11角色表"""
397 class Role(models.Model):
398     name = models.CharField(unique=True,max_length=32)#角色名#CharField定长文本#角色名不可以重复#最长度=32字节
399     def __str__(self):#__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
400         return self.name#返回 #角色名
401     class Meta: #通过一个内嵌类 "class Meta" 给你的 model 定义元数据
402         verbose_name_plural = "11角色表" #verbose_name_plural给你的模型类起一个更可读的名字
403 
404 """12标签表"""
405 class Tag(models.Model):
406     name =  models.CharField(max_length=64,unique=True) #标签名#CharField定长文本#最长度=64字节#不可以重复
407     def __str__(self): #__str__()是Python的一个“魔幻”方法,这个方法定义了当object调用str()时应该返回的值。
408         return self.name #返回 #标签名
409     class Meta:#通过一个内嵌类 "class Meta" 给你的 model 定义元数据
410         verbose_name_plural =  "12标签表" #verbose_name_plural给你的模型类起一个更可读的名字
411 
412 # ————————01PerfectCRM基本配置ADMIN————————
#models.py

 

 

 

 

 

 

  1 #admin.py
  2 # ————————01PerfectCRM基本配置ADMIN————————
  3 from django.contrib import admin
  4 # Register your models here.
  5 from crm import models #从crm导入models
  6 
  7 # ————————24PerfectCRM实现King_admin自定义操作数据————————
  8 from django.shortcuts import render
  9 # ————————24PerfectCRM实现King_admin自定义操作数据————————
 10 
 11 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
 12 from django import forms
 13 from django.contrib.auth.admin import UserAdmin
 14 from django.contrib.auth.forms import ReadOnlyPasswordHashField
 15 from crm.models import UserProfile
 16 #重写admin
 17 class UserCreationForm(forms.ModelForm):
 18     """  一个表单来创建新用户。包括所有必需的
 19   字段,加上重复密码。"""
 20     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
 21     password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
 22     class Meta:
 23         model = UserProfile
 24         fields = ('email', 'name')
 25     def clean_password2(self):
 26         # 检查两个密码条目匹配
 27         password1 = self.cleaned_data.get("password1")
 28         password2 = self.cleaned_data.get("password2")
 29         if password1 and password2 and password1 != password2:
 30             raise forms.ValidationError("密码不匹配")
 31         return password2
 32     def save(self, commit=True):
 33         #保存密码散列的格式提供
 34         user = super(UserCreationForm, self).save(commit=False)
 35         user.set_password(self.cleaned_data["password1"])
 36         if commit:
 37             user.save()
 38         return user
 39 #重写admin
 40 class UserChangeForm(forms.ModelForm):
 41     """更新用户的一种形式。包括所有字段
 42   用户,但取代了管理员的密码字段
 43   密码散列显示领域。
 44     """
 45     password = ReadOnlyPasswordHashField(label="Password",
 46         help_text=("原始密码不存储,所以没有办法看到"
 47                     "这个用户的密码,但是你可以改变密码 "
 48                     "使用 <a href=\"../password/\">修改密码</a>."))#哈值
 49     class Meta:
 50         model = UserProfile
 51         fields = ('email', 'password', 'name', 'is_active', 'is_superuser')
 52     def clean_password(self):
 53         # 不管用户提供什么,返回初始值。
 54         # 这是在这里,而不是在球场上,因为
 55         # 字段没有对初始值的访问
 56         return self.initial["password"]
 57 #重写admin
 58 class UserProfileAdmin(UserAdmin):#用户类,继承上一个类 UserAdmin
 59     # 单添加和更改用户实例
 60     form = UserChangeForm
 61     add_form = UserCreationForm
 62 
 63     # 字段用于显示用户模型。
 64     # 这些覆盖定义UserAdmin固定在底座上
 65     # auth.User引用特定字段。
 66     list_display = ('email', 'name','is_active', 'is_superuser', ) #显示字段表头
 67     list_filter = ('is_superuser',) # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
 68     fieldsets = (                 #自定义显示字段
 69         (None, {'fields': ('email','name', 'password')}),
 70         ('个人信息', {'fields': ( 'email','name')}),
 71         ('用户权限', {'fields': ('is_active','is_superuser','groups','user_permissions')}),#后台显示配置
 72     )
 73     #添加自定义字段
 74     # 覆盖get_fieldsets时使用这个属性创建一个用户。
 75     add_fieldsets = (
 76         (None, {
 77             'classes': ('wide',),
 78             'fields': ('email', 'name', 'password1', 'password2')}
 79         ),
 80     )
 81     search_fields = ('email',) #搜索(不能包含CharField)(注意加 逗号 , )
 82     ordering = ('email',) #自定义排序,默认'-id'
 83     filter_horizontal = ('groups','user_permissions', ) #复选框
 84 
 85 # 现在注册这个新UserAdmin ,因为我们不在使用Django的内置权限
 86 admin.site.register(UserProfile, UserProfileAdmin)
 87 #注销 原来的  # admin.site.register(models.UserProfile)   #10账号表
 88 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
 89 
 90 # ————————04PerfectCRM实现King_admin注册功能————————
 91 class CustomerAdmin(admin.ModelAdmin):#定制Djanago admin
 92     list_display = ('id','qq','source','consultant','content','date')#显示字段表头
 93     # ————————11PerfectCRM实现King_admin分页显示条数————————
 94     list_per_page = 2  #分页条数
 95     # ————————11PerfectCRM实现King_admin分页显示条数————————
 96     # ————————16PerfectCRM实现King_admin日期过滤————————
 97     # ————————15PerfectCRM实现King_admin多条件过滤————————
 98     # 过滤器(可以包含ManyToManyField) (注意加 逗号 , )
 99     # list_filter = ('source','consultant','consult_courses',)
100     list_filter = ('date','source','consultant','consult_courses',)
101     # ————————15PerfectCRM实现King_admin多条件过滤————————
102     # ————————16PerfectCRM实现King_admin日期过滤————————
103     # ————————18PerfectCRM实现King_admin搜索关键字————————
104     #搜索(不能包含CharField)(注意加 逗号 , )
105     search_fields = ('name','qq',)
106     # ————————18PerfectCRM实现King_admin搜索关键字————————
107 
108     # ————————26PerfectCRM实现King_admin自定义排序————————
109     ordering = ['-qq'] #自定义排序,默认'-id'
110     # ————————26PerfectCRM实现King_admin自定义排序————————
111 
112     # ————————27PerfectCRM实现King_admin编辑复选框————————
113     filter_horizontal = ('tags',) #复选框
114     # ————————27PerfectCRM实现King_admin编辑复选框————————
115 
116     # ————————28PerfectCRM实现King_admin编辑限制————————
117     readonly_fields = ('qq','consultant',) # 不可修改
118     # ————————28PerfectCRM实现King_admin编辑限制————————
119 
120 
121 
122     # ————————24PerfectCRM实现King_admin自定义操作数据————————
123     # from django.shortcuts import render
124     actions = ['test_actions',]#定制功能    #测试返回到一个新页面
125     def test_actions(self,request,arg2):#对应的函数 #request类自己的请求  #arg2类的内容
126         return render(request,"king_admin/table_index.html")
127     test_actions.short_description = "测试显示中文"
128     # ————————24PerfectCRM实现King_admin自定义操作数据————————
129 # ————————04PerfectCRM实现King_admin注册功能————————
130 
131 #注册到 Django Admin里
132 admin.site.register(models.Branch)                  #01校区表
133 admin.site.register(models.ClassList)               #02班级表
134 admin.site.register(models.Course)                  #03课程表,可以报名那些课程
135 
136 # ————————04PerfectCRM实现King_admin注册功能————————
137 # admin.site.register(models.Customer)                #04客户信息表
138 admin.site.register(models.Customer,CustomerAdmin)                #04客户信息表
139 # ————————04PerfectCRM实现King_admin注册功能————————
140 
141 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
142 admin.site.register(models.ContractTemplate)            #合同模版
143 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
144 
145 
146 
147 admin.site.register(models.CustomerFollowUp)        #05客户跟进表
148 admin.site.register(models.Enrollment)              #06学员报名信息表
149 admin.site.register(models.Payment)                 #07缴费记录表
150 admin.site.register(models.CourseRecord)            #08每节课上课纪录表
151 admin.site.register(models.StudyRecord)             #09学习纪录
152 
153 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
154 # admin.site.register(models.UserProfile)             #10账号表
155 # ————————35PerfectCRM实现CRM重写Admin密码修改————————
156 
157 admin.site.register(models.Role)                    #11角色表
158 admin.site.register(models.Tag)                     #12标签表
159 
160 '''
161 Django Admin里账号密码重置方法
162 #运行 Terminal  
163 
164 python manage.py createsuperuser
165 
166 Username :              admin
167 Email address:          admin@qq.com
168 Password:               admin123456
169 Password (again):       admin123456
170 
171 
172 英文转中文方法
173 到settings.py里修改
174 # LANGUAGE_CODE = 'en-us'
175 LANGUAGE_CODE = 'zh-Hans'
176 '''
177 
178 # ————————01PerfectCRM基本配置ADMIN————————
#admin.py

 

 

 

#运行 Terminal
# 生成 数据表
# python manage.py makemigrations
# 数据表 迁移
# python manage.py migrate

 

 

 

 1 # DBadd_urls.py
 2 # ————————03PerfectCRM创建基本数据————————
 3 from django.conf.urls import url
 4 from DBadd import auth_views
 5 from DBadd import crm_views
 6 
 7 urlpatterns = [
 8     url(r'^auth_user/$', auth_views.auth_user), #Django账号表
 9 
10     url(r'^crm_Role/$', crm_views.crm_Role), #角色表 等基本信息
11     url(r'^crm_UserProfile/$', crm_views.crm_UserProfile),#账号表 #随机学生
12     url(r'^crm_userprofile_roles/$', crm_views.crm_userprofile_roles),#账号角色关联表 #随机学生
13 
14     url(r'^crm_Customer/$', crm_views.crm_Customer),  # 04客户信息表
15 
16     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
17     url(r'^crm_ContractTemplate/$', crm_views.crm_ContractTemplate),  # 角色表 等基本信息
18     # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
19 ]
20 # ————————03PerfectCRM创建基本数据————————
# DBadd_urls.py

 

 

  1 # crm_views.py
  2 
  3 # ————————03PerfectCRM创建基本数据————————
  4 
  5 from django.shortcuts import render
  6 from django.shortcuts import redirect
  7 from django.shortcuts import HttpResponse
  8 
  9 
 10 from crm import models
 11 from django.contrib.auth import models as auth_models
 12 
 13 #随机字符串
 14 import random
 15 from random import choice
 16 
 17 #添加"""基本数据"""
 18 def crm_Role(request):
 19     if request.method == "GET":
 20         user_list = models.Role.objects.all()
 21         return render(request, 'crm_Role.html', {'user_list':user_list})
 22     elif request.method == "POST":
 23         try:
 24             models.Role.objects.create(name='角色学生')
 25             models.Role.objects.create(name='角色销售')
 26             models.Role.objects.create(name='角色老师')
 27             models.Role.objects.create(name='角色校长')
 28             models.Role.objects.create(name='角色系统维护')
 29 
 30             models.Branch.objects.create(name='北京校区',addr='北京天安门')
 31             models.Branch.objects.create(name='广东校区',addr='广东东莞市')
 32             models.Branch.objects.create(name='上海校区',addr='上海黄浦江')
 33             models.Branch.objects.create(name='福建校区',addr='福建仙游县')
 34             models.Branch.objects.create(name='四川校区',addr='四川成都市')
 35 
 36             models.Tag.objects.create(name='好,很好')
 37             models.Tag.objects.create(name='很有兴趣')
 38             models.Tag.objects.create(name='兴趣不大')
 39             models.Tag.objects.create(name='交钱很爽快')
 40             models.Tag.objects.create(name='随便问问的')
 41 
 42             models.Course.objects.create(name='Pyton',price='6666',period='40',outline='Python , 是一种面向对象的解释型计算机程序设计语言,具有丰富和强大的库,Python 已经成为继JAVA,C++之后的的第三大语言。 特点:简单易学、免费开源、高层语言、可移植性强、面向对象、可扩展性、可嵌入型、丰富的库、规范的代码等。')
 43             models.Course.objects.create(name='PHP',price='8888',period='50',outline='PHP语言是目前Web后端开发使用最广泛的语言,几乎绝大多数网站使用。PHP开发快速,开发成本低,周期短,后期维护费用低,开源产品丰富。')
 44             models.Course.objects.create(name='Java',price='9999',period='60',outline='完成本套餐的学习,学员可以全面掌握后续JavaEE开发所需的Java技术,为后续学习JavaEE开发打下坚实的基础。')
 45 
 46             # ————————47PerfectCRM实现CRM客户报名流程————————
 47 
 48             # models.UserProfile.objects.create(name='ADMIN系统维护', user_id=1)
 49             # models.UserProfile.objects.create(name='李白销售老师', user_id=2)
 50             # models.UserProfile.objects.create(name='杜甫销售老师', user_id=3)
 51             # models.UserProfile.objects.create(name='唐伯虎销售老师', user_id=4)
 52             # models.UserProfile.objects.create(name='颜真卿老师', user_id=5)
 53             # models.UserProfile.objects.create(name='罗贯中老师', user_id=6)
 54             # models.UserProfile.objects.create(name='白居易老师', user_id=7)
 55             # models.UserProfile.objects.create(name='施耐庵老师', user_id=8)
 56             # models.UserProfile.objects.create(name='曹雪芹校长', user_id=9)
 57 
 58 
 59             models.UserProfile.objects.create(last_login='2018-04-18', email='admin@qq.com',name='admin',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 60             models.UserProfile.objects.create(last_login='2018-04-18', email='admin1@qq.com',name='admin1',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 61             models.UserProfile.objects.create(last_login='2018-04-18', email='admin2@qq.com',name='admin2',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 62             models.UserProfile.objects.create(last_login='2018-04-18', email='admin3@qq.com',name='admin3',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 63             models.UserProfile.objects.create(last_login='2018-04-18', email='admin4@qq.com',name='admin4',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 64             models.UserProfile.objects.create(last_login='2018-04-18', email='admin5@qq.com',name='admin5',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 65             models.UserProfile.objects.create(last_login='2018-04-18', email='admin6@qq.com',name='admin6',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 66             models.UserProfile.objects.create(last_login='2018-04-18', email='admin7@qq.com',name='admin7',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 67             models.UserProfile.objects.create(last_login='2018-04-18', email='admin8@qq.com',name='admin8',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 68             models.UserProfile.objects.create(last_login='2018-04-18', email='admin9@qq.com',name='admin9',is_active=1,is_superuser=1,password='pbkdf2_sha256$100000$cCkwdwzBiea6$VNOFkD7HAKwsjKXsDZMOGO8ct3EpVMaX2JPU+h5PK9E=')
 69             # ————————47PerfectCRM实现CRM客户报名流程————————
 70 
 71             models.ClassList.objects.create(class_type=1,semester=2,start_date='2018-03-20',branch_id=1,course_id=1)
 72             models.ClassList.objects.create(class_type=0,semester=5,start_date='2018-03-20',branch_id=1,course_id=1)
 73             models.ClassList.objects.create(class_type=2,semester=8,start_date='2018-03-20',branch_id=1,course_id=1)
 74             models.ClassList.objects.create(class_type=0,semester=1,start_date='2018-03-20',branch_id=1,course_id=1)
 75             models.ClassList.objects.create(class_type=1,semester=3,start_date='2018-03-20',branch_id=1,course_id=1)
 76             models.ClassList.objects.create(class_type=0,semester=9,start_date='2018-03-20',branch_id=1,course_id=1)
 77             models.ClassList.objects.create(class_type=2,semester=6,start_date='2018-03-20',branch_id=1,course_id=1)
 78             models.ClassList.objects.create(class_type=1,semester=20,start_date='2018-03-20',branch_id=1,course_id=1)
 79             models.ClassList.objects.create(class_type=0,semester=32,start_date='2018-03-20',branch_id=1,course_id=1)
 80 
 81 
 82         except:
 83             return HttpResponse('基本数据已经添加了。。。')
 84 
 85         return  redirect('/DBadd/crm_Role/')
 86 
 87 
 88 
 89 #添加"""10账号表"""  #随机学生
 90 def crm_UserProfile(request):
 91     if request.method == "GET":
 92         user_list = models.UserProfile.objects.all()
 93         return render(request, 'crm_UserProfile.html', {'user_list':user_list})
 94     elif request.method == "POST":
 95         for i in range(50):
 96 
 97             Rword = ''.join(''.join([chr(random.randint(0x4E00, 0x9FBF)) for i in range(3)]).split())# 随机中文
 98             n=Rword
 99 
100             
101             a = models.UserProfile.objects.values("user_id").all()
102             e = auth_models.User.objects.values("id").all()
103             print('eeeee', e, type(e))
104             x=e.difference(a)
105             # for i in x:
106             #     print('zzz', x, type(x))
107 
108             l=[]
109             for i in x:
110                 l.append(i['id'])
111             print('llll', l, type(l))
112 
113             if len(l)==0:
114                 return HttpResponse('请添加 admin的用户后,再来添加。。。')
115             else:
116                 c = choice(l)
117                 u = c
118                 models.UserProfile.objects.create(name=n, user_id=u)
119         return redirect('/DBadd/crm_UserProfile/')
120 
121 #添加"""10账号表--11角色表""" #随机学生
122 def crm_userprofile_roles(request):
123     if request.method == "GET":
124         user_list = models.UserProfile.objects.all()
125         role_list = models.Role.objects.get(id=1)
126         return render(request, 'crm_userprofile_roles.html', {'user_list':user_list,'role_list':role_list})
127     elif request.method == "POST":
128         try:
129             for i in range(50):
130                 b1 = models.Role.objects.get(id=1)
131                 a=b1.userprofile_set.values("id").all()
132 
133                 e = models.UserProfile.objects.values("id").all()
134                 x = e.difference(a)
135 
136                 l = []
137                 for i in x:
138                     l.append(i['id'])
139                 print('llll', l, type(l))
140 
141                 if len(l) == 0:
142                     return HttpResponse('请添加 数据 后,再来添加。。。')
143                 else:
144                     c = choice(l)
145                     print('c', c, type(c))
146 
147                     g1 = models.UserProfile.objects.get(id=c)
148                     b1 = models.Role.objects.get(id=1)
149                     g1.roles.add(b1)
150             return redirect('/DBadd/crm_userprofile_roles/')
151         except:
152             return HttpResponse('没有数据了。。。')
153 
154 
155 
156 
157 # 添加"""04客户信息表"""
158 def crm_Customer(request):
159     if request.method == "GET":
160         user_list = models.Customer.objects.all()
161         return render(request, 'crm_Customer.html', {'user_list': user_list})
162     elif request.method == "POST":
163         for i in range(50):
164             Rword = ''.join(''.join([chr(random.randint(0x4E00, 0x9FBF)) for i in range(3)]).split())  # 随机中文
165             r=random.randint(5,18)
166             Num = "".join(random.choice("0123456789") for i in range(r))  # 随机数字 #保证qq的唯一性
167             Cnum = "".join(random.choice("123456789") for i in range(1))  # 随机数字  #id 不能选择0
168             try:
169                 models.Customer.objects.create(name=Rword, qq=Num, qq_name=Rword, phone=Num, source=1,
170                                                referral_from=Rword, consult_courses_id=1, content=Rword,
171                                                consultant_id=Cnum, memo=Rword, date='2018-03-20')
172             except:
173                 return HttpResponse('数据重复了。。。')
174 
175         return redirect('/DBadd/crm_Customer/')
176 
177 
178 # ————————03PerfectCRM创建基本数据————————
179 
180 
181 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
182 def crm_ContractTemplate(request):
183     if request.method == "GET":
184         user_list = models.ContractTemplate.objects.all()
185         return render(request, 'crm_ContractTemplate.html', {'user_list':user_list})
186     elif request.method == "POST":
187         try:
188             t= '''
189             委托方:__{stu_name}__ 
190   法定代表人或负责人:__{stu_name}__ 
191   服务方:_______ 
192   法定代表人或负责人:_________ 
193   根据《中华人民共和国合同法》的有关规定,经双方当事人协商一致,签订本 
194 合同。 
195   第一条 项目名称__{course_name}__。 
196   (注:本参考格式适用于下列技术服务活动:进行设计、工艺、制造、试验以 
197 及农作物育种,畜禽的饲养等方面的技术指导、讲解技术资料、解决和解答技术问 
198 题;进行示范操作;传授计算机软件的编制技术、先进仪器设备的装配,使用技术 
199 等等。) 
200   第二条 培训的内容和要求:_______。 
201   第三条 培训计划、进度、期限:_______。 
202   第四条 培训地点和方式:____________。 
203   第五条 服务方(教师)的资历和水平:________。 
204   第六条 学员的人数和质量:___________。 
205   第七条 教员、学员的食宿、交通、医疗费用的支付和安排____。 
206   第八条 报酬及其支付方式:__________。 
207   第九条 委托方的违约责任:_________。 
208   1.委托方未按合同提供培训条件,影响合同履行的,约定的报酬仍应如数支 
209 付; 
210   2.擅自将服务方要求保密的技术资料引用、发表和提供给第三方,应支付数 
211 额为____的违约金; 
212   第十条 服务方的违约责任: 
213   1.服务方未按合同制订培训计划,影响培训工作质量的,应当减收___% 
214 的报酬; 
215   2.服务方提供的师资不符合合同要求,服务方有义务予以重新配备;未按合 
216 同规定完成培训工作的,应免收报酬。 
217   第十一条 保密条款:________ 
218   当事人双方应对下列技术资料承担保密义务:______。 
219   第十二条 有关技术成果归属条款 
220   在履行合同过程中,服务方利用委托方提供的技术资料和工作条件所完成的新 
221 的技术成果,属于服务方;委托方利用服务方的工作成果所完成的新技术成果,属 
222 于委托方。对新的技术成果享有就该技术成果取得的精神权利(如获得奖金、奖章、 
223 荣誉证书的权利)、经济权利(如专利权、非专利技术的转让权,使用权等)和 
224 其它利益。 
225   第十三条 本合同争议的解决办法:______。 
226   本合同自双方当事人签字、盖章后生效。
227 委托方负责人(或授权代表)      服务方负责人(或授权代表) 
228   签字:__{stu_name}__(盖章)     签名:____(盖章) 
229   签字时间:_________     签字时间:_________ 
230   签字地点:_________     签字地点:_________ 
231   开户银行:_________     开户银行:_________ 
232   帐号:___________     帐号:___________ 
233   委托方担保人(名称):___     服务方担保人(名称):___ 
234   地址:___________     地址:___________ 
235   负责人(或授权代表)         负责人(或授权代表) 
236   签字:________(盖章)    签字:________(盖章) 
237   签字时间:_________     签字时间:_________ 
238   签字地点:_________     签字地点:_________ 
239   开户银行:_________     开户银行:_________ 
240   帐号:___________     帐号:___________'''
241 
242             models.ContractTemplate.objects.create(name='技术合同:专业技术培训协议',template=t)
243         except:
244             return HttpResponse('数据错误!重复了吧。。。')
245 
246         return  redirect('/DBadd/crm_ContractTemplate/')
247 
248 # ————————48PerfectCRM实现CRM客户报名流程学生合同————————
# crm_views.py

 

 

 

 1 {#crm_ContractTemplate.html#}
 2 {## ————————48PerfectCRM实现CRM客户报名流程学生合同————————#}
 3 <!DOCTYPE html>
 4 <html lang="en">
 5 <head>
 6     <meta charset="UTF-8">
 7     <title>Title</title>
 8 </head>
 9 <body>
10             <h3>添加合同</h3>
11 
12             <form method="POST" action="/DBadd/crm_ContractTemplate/">
13                  {% csrf_token %}
14                 <input type="submit"value="添加"/>
15             </form>
16 
17             <h3>合同详细</h3>
18             <ul>
19                 {% for row in user_list %}
20                     <li>
21 
22                         <a>{{row.id}}-{{row.name}}</a>
23                         <hr>
24                         <pre>{{row.template}}</pre>
25                     </li>
26                 {% endfor %}
27             </ul>
28 
29 
30 </body>
31 </html>
32 
33 {## ————————48PerfectCRM实现CRM客户报名流程学生合同————————#}
{#crm_ContractTemplate.html#}

 

 

http://127.0.0.1:8000/DBadd/crm_ContractTemplate/

 

http://127.0.0.1:8000/bpm/customer/registration/1/

 

posted @ 2018-04-19 14:41  颜言  阅读(611)  评论(0编辑  收藏  举报