第十一章、學員報名流程開發 1
11.1.面包屑的制作

(1)table_obj_list.html頁面面包屑
def table_obj_list
返回數據改成locals()

table_obj_list.html

kingadmin_tags.py
@register.simple_tag def get_model_verbose_name(admin_class): return admin_class.model._meta.verbose_name
(2)change頁面的面包屑
table_obj_change.html
<ol class="breadcrumb"> <li><a href="/kingadmin/">Home</a></li> <li><a href="/kingadmin/{{ app_name }}">{{ app_name }}</a></li> <li><a href="/kingadmin/{{ app_name }}/{{ model_name }}/">{% get_model_verbose_name admin_class %}</a></li> <li class="active">{{ form_obj.instance }}</li> </ol> <h4 class="page-header">修改{{ form_obj.instance }}</h4>
(3)add頁面的面包屑
因為add和change共用tags和html。所以要添加判斷是add還是change
table__obj_change_component.html

kingadmin_tags.py


table_obj_add.html
<ol class="breadcrumb"> <li><a href="/kingadmin/">Home</a></li> <li><a href="/kingadmin/{{ app_name }}">{{ app_name }}</a></li> <li><a href="/kingadmin/{{ app_name }}/{{ model_name }}/">{% get_model_verbose_name admin_class %}</a></li> <li class="active">ADD {{ model_name }}</li> </ol> <h2 class="page-header">{% get_model_name admin_class %}</h2> <h4 class="page-header">添加{% get_model_name admin_class %}</h4>
11.2.報名流程和models設計
(1)后台修改左側“客戶庫”的url

(2)左側menu菜單添加“active”樣式
kingadmin/index.html
如果當前的url 跟menu的url_name就添加“active”
<ul class="nav nav-sidebar"> {% for role in request.user.userprofile.role.select_related %} {% for menu in role.menus.select_related %} {% if request.path == menu.url_name %} <li class="active"><a href="{% if menu.url_type == 0 %}{{ menu.url_name }}{% else %}{% url menu.url_name %}{% endif %}">{{ menu.name }}</a></li> {% else %} <li ><a href="{% if menu.url_type == 0 %}{{ menu.url_name }}{% else %}{% url menu.url_name %}{% endif %}">{{ menu.name }}</a></li> {% endif %} {% endfor %} {% endfor %} </ul>
報名流程
- 銷售 發起報名流程,選擇班級,發報名鏈接給學員
- 學員 填寫在線報名表,提交gerenxinxi,上傳證件信息,同意培訓協議
- 銷售 審核報名表,審核通過后,創建一條繳費記錄,自動把學員添加到相應的班級,報名成功
models設計
添加三張表 crm/models.py
class ContractTemplate(models.Model): '''存儲合同模板''' name = models.CharField(max_length=64) content = models.TextField() date = models.DateField(auto_now_add=True) class StudentEnrollment(models.Model): """學員報名表""" customer = models.ForeignKey('CustomerInfo',on_delete=models.CASCADE) class_grade = models.ForeignKey('ClassList',on_delete=models.CASCADE) consultant = models.ForeignKey('UserProfile',on_delete=models.CASCADE) contract_agreed = models.BooleanField(default=False) contract_signed_date = models.DateTimeField(blank=True,null=True) contract_approved = models.BooleanField(default=False) consultant_approved_date = models.DateTimeField('合同審核時間',blank=True,null=True) class Meta: unique_together = ('customer','class_grade') def __str__(self): return '%s'% self.customer class PaymentRecord(models.Model): '''存儲學員繳費記錄''' enrollment = models.ForeignKey('StudentEnrollment',on_delete=models.CASCADE) payment_type_choices = ((0,'報名費'),(1,'學費'),(2,'退費')) payment_type = models.SmallIntegerField(choices=payment_type_choices,default=0) amount = models.IntegerField('費用',default=500) consultant = models.ForeignKey('UserProfile',on_delete=models.CASCADE) date = models.DateTimeField(auto_now_add=True) def __str__(self): return '%s' %self.enrollment
班級關聯合同表

修改student跟customer為一對一的關系

11.3.報名頁面
流程
- 銷售填寫客戶跟班級,點“下一步”提交
- 后台獲取到客戶id和班級id,在數據庫中創建記錄,並生成一個報名鏈接,返回到前端
- 前端顯示報名鏈接,然后銷售把報名鏈接發給用戶
(1)crm/urls.py
# crm/urls.py from django.conf.urls import url,include from crm import views urlpatterns = [ url(r'^$', views.dashboard,name='sales_dashboard'), #學員報名 url(r'^stu_enrollment/$', views.stu_enrollment,name='stu_enrollment'), ]
(2)crm/views.py
@login_required def stu_enrollment(request): customers = models.CustomerInfo.objects.all() class_lists = models.ClassList.objects.all() if request.method == 'POST': #獲取提交的客戶id和班級id,然后生成報名鏈接 customer_id = request.POST.get('customer_id') class_grade_id = request.POST.get('class_grade_id') enrollment_obj = models.StudentEnrollment.objects.create( customer_id = customer_id, class_grade_id = class_grade_id, consultant_id = request.user.userprofile.id ) #生成鏈接返回到前端 enrollment_link = "http://localhost:8000/crm/enrollment/%s"% enrollment_obj.id return render(request,'crm/stu_enrollment.html',locals())
(3)新建templates/crm/stu_enrollment.html
crm/index.html

crm/stu_enrollment.html
{#templates/crm/stu_enrollment.html#} {% extends 'index.html' %} {% block right-content-container %} <h3>學員報名頁</h3> <form class="form-horizontal" method="post"> {% csrf_token %} <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">客戶</label> <div class="col-sm-10"> <select name="customer_id" class="form-control"> {% for customer in customers %} <option value="{{ customer.id }}">{{ customer }}</option> {% endfor %} </select> </div> </div> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">報名班級</label> <div class="col-sm-10"> <select name="class_grade_id" class="form-control"> {% for class_grade in class_lists %} <option value="{{ class_grade.id }}">{{ class_grade }}</option> {% endfor %} </select> </div> </div> <input type="submit" class="btn btn-success pull-right" value="下一步"> </form> {% if enrollment_link %} <p>請將此報名鏈接復制並發送給學員填寫 {{ enrollment_link }}</p> {% endif %} {% endblock %}

11.4.學員填寫報名信息
- 添加學員注冊url
- 添加CustomerInfo字段,身份證信息,緊急聯絡人,性別
- 有些字段是只讀的,填寫信息的時候不能修改,因為如果設置了只讀(添加屬性disabled=true),提交的時候會報這些字段為空,導致提交錯誤
- 所以在前段添加了js代碼,BeforeFormSubmit 在提交前去掉disable=true(因為數據庫中有默認值,提交的時候就不會報錯)
- 防止用戶通過前端改html代碼的方式改只讀字段的信息,所以在form.py里面添加了一個自定義的驗證方法(clean),如果只讀字段提交的時候信息跟數據庫中默認的不一樣,就報錯
(1)crm/urls.py
# crm/urls.py from django.conf.urls import url,include from crm import views urlpatterns = [ url(r'^$', views.dashboard,name='sales_dashboard'), #學員報名 url(r'^stu_enrollment/$', views.stu_enrollment,name='stu_enrollment'), #學員注冊 url(r'^enrollment/(\d+)/$', views.enrollment,name='enrollment'), ]
(2)crm/models.py
CustomerInfo表 添加字段

(3)crm/form.py
# crm/form.py from django.forms import ModelForm from crm import models from django import forms class CustomerForm(ModelForm): class Meta: model = models.CustomerInfo fields = "__all__" #不顯示的字段 exclude = ['consult_content','status','consult_courses'] #只讀的字段 readonly_fields = ['contact_type','contact','consultant','referral_from','source'] #django是通過“__new__”方法,找到ModelForm里面的每個字段的,然后循環出每個字段添加自定義樣式 def __new__(cls, *args, **kwargs): #cls.base_fields是一個元祖,里面是 所有的 【(字段名,字段的對象),(),()】 for field_name in cls.base_fields: field_obj = cls.base_fields[field_name] #添加屬性 field_obj.widget.attrs.update({'class':'form-control'}) if field_name in cls.Meta.readonly_fields: field_obj.widget.attrs.update({'disabled':'true'}) return ModelForm.__new__(cls) #只讀字段不讓用戶通過瀏覽器改html代碼的方式改 def clean(self): # 表單級別的錯誤 if self.errors: raise forms.ValidationError(("Please fix errors before re-submit.")) # means this is a change form ,should check the readonly fields if self.instance.id is not None: #取出只讀字段,是一個字符串形式 for field in self.Meta.readonly_fields: #通過反射取出字段的值(數據庫里的數據) old_field_val = getattr(self.instance, field) #提交過來的數據 form_val = self.cleaned_data.get(field) #如果兩個數據不匹配 if old_field_val != form_val: #就提示只讀字段不能修改 #add_error是字段級別的錯誤 self.add_error(field, "Readonly Field: field should be '{value}' ,not '{new_value}' ". \ format(**{'value': old_field_val, 'new_value': form_val}))
(4)crm/views.py
def enrollment(request,enrollment_id): '''學員在線報名表地址''' enrollment_obj = models.StudentEnrollment.objects.get(id=enrollment_id) if request.method == 'POST': customer_form = form.CustomerForm(instance=enrollment_obj.customer,data=request.POST) if customer_form.is_valid(): customer_form.save() return HttpResponse("你已成功提交報名信息,請等待審核,歡迎加入仙劍奇俠傳") else: customer_form = form.CustomerForm(instance=enrollment_obj.customer) return render(request,'crm/enrollment.html',locals())
(4)crm/enrollment.html
{#templates/crm/enrollment.html#} {% extends 'index.html' %} {% block body %} <div class="container"> <h3>仙劍奇俠傳|學員報名</h3> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title">學員在線報名</h3> </div> <div class="panel-body"> <form class="form" method="post" onsubmit="return BeforeFormSubmit(this)"> {% csrf_token %} {% for field in customer_form %} <div class="form-group col-lg-6"> <label class="col-sm-2 control-label">{{ field.label }}</label> <div class="col-sm-10"> {{ field }} <span style="color: red;">{{ field.errors.0 }}</span> </div> </div> {% endfor %} <div class="form-group col-lg-6"> <label class="col-sm-2 control-label">報名班級</label> <div class="col-sm-10"> {{ enrollment_obj.class_grade }} </div> </div> <div class="form-group col-lg-6"> <label class="col-sm-2 control-label">學費</label> <div class="col-sm-10"> {{ enrollment_obj.class_grade.course.price }} </div> </div> <div class="col-sm-offset-11 col-sm-2"> <input type="submit" class="btn btn-success " value="提交"> </div> </form> </div> <div class="panel-footer"><a href="http://www.cnblogs.com/derek1184405959/">zhang_derek</a></div> </div> </div> <script> function BeforeFormSubmit(ele) { $(":disabled").removeAttr("disabled"); } </script> {% endblock %}
在線報名填表頁面

修改只讀字段會報錯

