前言: 今晚寫一篇關于學員/講師/銷售員CRM系統(tǒng)。這個小項目是27號開始做的,大概搞了一星期不到。我把一些知識點總結下,還寫下當時克服的BUG。

 

Django練習小項目:學員管理系統(tǒng)設計開發(fā)

帶著項目需求學習是最有趣和效率最高的,今天就來基于下面的需求來繼續(xù)學習Django 

項目需求:

  1. 分講師\學員\課程顧問角色

  2. 學員可以屬于多個班級,學員成績按課程分別統(tǒng)計

  3. 每個班級至少包含一個或多個講師

  4. 一個學員要有狀態(tài)轉化的過程 ,比如未報名前,報名后,畢業(yè)老學員

  5. 客戶要有咨詢紀錄, 后續(xù)的定期跟蹤紀錄也要保存

  6. 每個學員的所有上課出勤情況\學習成績都要保存

  7. 學??梢杂蟹中^(qū),默認每個校區(qū)的員工只能查看和管理自己校區(qū)的學員

  8. 客戶咨詢要區(qū)分來源

拿到需求后,先要分析,再設計表結構: 超級重要!!

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓 View Code

 

先來張圖看看效果: 下圖是銷售員Alex登陸后看到的界面

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

點擊右上方Alex已招學員,出現(xiàn)下圖界面:

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 

一、前端界面實現(xiàn)

界面看著我感覺是蠻漂亮的,登陸界面信息界面都是搞bootstrap模版的。只要將bootstrap模版修改下,就變成所需要的界面啦。不會修改的可以看看如何使用bootstrap。

 

二、字數顯示限制

如果備注過多,會使界面不好看,要想使備注只顯示一定的字數,可用下列方法: 只顯示13個字節(jié)

1
<td>{{ customer.consult_memo|truncatechars:13}}</td>

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 

三、報名狀態(tài)加色

第一種方法,比較麻煩,有興趣可看django進階-modelform&admin action

第二種方法更簡單

1. 在bootstrap添加自定義的css樣式文件,custom.css

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

2. 在基礎模版(我定義的是base.html,其它html模塊是繼承它的)導入custom.css文件:

1
<link href="/static/bootstrap-3.3.7-dist/css/custom.css" rel="stylesheet">

3. 你隨意在custom.css定義樣式

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓 View Code

4. 在對應的customer.html的標簽加入樣式; customer.status是后臺傳給前端的,是學生的報名狀態(tài)。

1
<td class="{{ customer.status }}">{{ customer.get_status_display }}</td>

  

四、分頁功能

其實Alex銷售員登陸后看到的界面只有兩條客戶的信息,這是我在后臺寫的。注意看左下角有個分頁,類似與百度搜索的分頁。其實分頁實現(xiàn)起來還是有點難度的。

先看django官方文檔。官方文檔寫得很詳細!!

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓 View Code

后臺實現(xiàn):

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 def customers(request): 2     print(">>>>request:",request) 3     # 查找所有客戶,獲取所有信息的結果集,但并不是所有信息都已經取出來了(如果有上萬條數據,不能一次性取出來,先取一部分), 4     customer_list = models.Customer.objects.all() 5     print(">>>>customers:", customer_list) 6     paginator = Paginator(customer_list, 2)  # 生成分頁實例: 每一頁有兩條數據 7     page = request.GET.get("page")  # 獲取前端點擊的頁數,參數page可自定義 8     try: 9         customer_objs = paginator.page(page)  # 生成第page頁的對象10     except PageNotAnInteger:11         # If page is not an integer, deliver first page12         # 如果輸入的頁碼不是下標,則返回第一頁13         customer_objs = paginator.page(1)14     except EmptyPage:15         # If page is out of range (e.g. 9999), deliver last page of results.16         # 如果輸入的頁碼超出,則跳轉到最后的頁碼17         customer_objs = paginator.page(paginator.num_pages)18 19     return render(request, "crm/customer.html", {"customer_list": customer_objs})

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

前端實現(xiàn):

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 <div class="pagination"> 2  3         <nav> 4            <ul class="pagination"> 5                {% if customer_list.has_previous %} 6                     <li class=""><a href="?page={{ customer_list.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li> 7                {% endif %} 8  9                {% for page_num in customer_list.paginator.page_range %}10                     <!-- abs_page為函數名,后兩個為參數 -->11                     {% abs_page customer_list.number page_num %}12 13                {% endfor %}14 15                {% if customer_list.has_next %}16                     <li class=""><a href="?page={{ customer_list.next_page_number }}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>17                {% endif %}18            </ul>19         </nav>20 21     </div>

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

第一次進入http://127.0.0.1:8000/crm/customer/頁面時,請求為get方式,后臺接收到的page參數為空,故會出PagenotAnInterger異常,故會返回到第一頁!!

注意前端的第九行代碼: customer_list.paginator.page_range是頁數的范圍。customer_list只是一個第幾頁的實例而已,是無法獲取到頁數的范圍的。

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

但是問題來了,如果,你有100條數據,每頁只放兩條數據,意味著界面得有50個button,基本上頁面是放不下的。

如果頁面過多,看下百度怎么處理

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

可用abs絕對值,若當前頁面為第6頁,想讓3、4、5和7、8、9也顯示出來,可在循環(huán)判斷頁面時,利用abs, 當|循環(huán)的頁面值-當前的頁面值|<=3 ,則顯示。
但問題又來了,前端的templates可沒有abs取絕對值這種后臺才有的方法,怎么辦??

 

自定義template tags

https://docs.djangoproject.com/es/1.9/howto/custom-template-tags/ 

效果圖:

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓  電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

后臺是如何自定義模版??

首先自定義templates模版,我隨便建了個文件custom_tags.py,必須放在新建包templatetags下

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

custom_tags.py: 當頁碼絕對值之差小于3時,則返回頁碼按鈕的html給前端,反之不返回。

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 1 from django import template 2 from django.utils.html import format_html 3   4 register = template.Library()  #django的語法庫 5  6   7 @register.simple_tag 8 def abs_page(current_page, loop_page): 9     offset = abs(current_page - loop_page)10     if offset < 3:11         if current_page == loop_page:12             page_ele = "<li class='active'><a href='?page=%s'>%s</a></li>" % (current_page, current_page)13         else:14             page_ele = "<li class=''><a href='?page=%s'>%s</a></li>" % (loop_page, loop_page)15         return format_html(page_ele)  #將字符串轉化為html,返回給前端16     else:17         return ""

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 

五、modelform進階

modelform之前有寫過,django進階-modelform&admin action, 但主要是寫django自帶的admin。

現(xiàn)在我有個需求,銷售員Alex想查看客戶的詳細信息。只需只擊客戶的ID號,便可查看,當然也可以修改。

前端:

1
<td><a href="/crm/customers/{{customer.id}}/">{{customer.id}}</a></td>

urls:

1
2
# 當學員id當作參數,傳給customer_detail方法
url(r'^customers/(\d+)/$', views.customer_detail),

后臺:

1
2
3
4
def customer_detail(request,customer_id):
    customer_obj = models.Customer.objects.get(id=customer_id)
    form = forms.CustomerModelForm()
    return render(request,"crm/customer_detail.html",{"customer_form":form})

看前端界面顯示: 雖然能顯示出表單,但無法顯示出學員的信息,而且太丑了!!

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

如何顯示出學員的信息:

1
2
customer_obj = models.Customer.objects.get(id=customer_id)
form = forms.CustomerModelForm(instance=customer_obj)  # 將數據對象當作參數傳入

如何使前端界面更漂亮:

forms.py表單文件:

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓 View Code

前端: 樣式是從bootstrap參考來的

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓 View Code

效果圖:

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

修改后保存信息

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓 View Code

 

六、必填與非必填字段

效果圖: 必填字段有加粗,且左上角有紅色*號

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

只需修改下前端代碼即可:

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

1 {% if field.field.required %} <!--若是必填字段 -->2     <label class="col-sm-2 control-label">3         <span style="color: red;font-size: larger">*</span>{{ field.label }}4     </label>5 {% else %} <!-- label在django默認為加粗 -->6     <label style="font-weight: normal" class="col-sm-2 control-label">{{ field.label }}</label>7 {% endif %}

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 

權限分配, 這個改天再寫博客整理下: 三個角色的權限是不同的。對銷售員來講,無法修改非本人招收客戶的信息。

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

 

七、url別名

啥是url別名??

1 #當學員id當作參數,傳給customer_detail方法,2 #給該url起別名,一調用別名customer_detail,就關聯(lián)上url3 url(r'^customers/(\d+)/$',views.customer_detail,name="customer_detail"),

現(xiàn)在銷售員想查看客戶的詳細信息,只需一點擊客戶的ID號便可查看。so, ID號必須是個a標簽,下面來看看前端實現(xiàn):

1 <!-- 這里查看學員的詳細信息不應該寫列,否則當url一改變,得來這里改代碼 -->2 <!-- <td><a href = " /crm/customers/ {{customer.id}} / "> {{ customer.id }} </a></td> -->3 4 <td><a href = "{% url  'customer_detail'  customer.id %}"> {{ customer.id }} </a></td>

注意了,如果不用url別名的話,就用第2行代碼。但是,這樣項目的可維護性大大降低了。當你需改動url時,必須到前端修改對應的a標簽。如果用了url別名,就不用再來前端修改了。

電腦培訓,計算機培訓,平面設計培訓,網頁設計培訓,美工培訓,Web培訓,Web前端開發(fā)培訓

看到沒,我用瀏覽器審查元素,瀏覽器已經自動將ID號的a標簽,轉化為一條url. 神奇!!

 

1.非系統(tǒng)的學習也是在浪費時間 2.做一個會欣賞美,懂藝術,會藝術的技術人