這個章節我們將演示用戶端界面的開發,當前演示界面還是采用先實現基本功能再逐步完善的“敏捷”模式。首先聚焦在功能邏輯方面實現普通用戶與系統的交互,普通用戶通過url能查看到當前任務的執行情況列表。為了便於開發我們先設定一個目標url是http://localhost:8001/task/顯示當前在執行的任務列表,同時,界面有操作按鈕來執行針對任務的操作。
這里頁面原型布局設計與Admin類似,如下圖:
1.1. 配置url和view
為了便於對django的每個APP的url進行統一管理,我們先給Task添加一個urls.py的文件,task app發布的url將在這個文件里組織。
接下來在新增的urls.py文件里增加如下代碼:
from django.urls import path from Task import views urlpatterns = [ path('', views.view_list,name='view_list'), ]
文件:Task/urls.py
同時,對應的在Task/views.py文件里增加函數view_list,代碼如下:
from django.shortcuts import render from django.http import HttpResponse def view_list(request): return HttpResponse('hello world!')
現在我們在IndDemo/urls.py文件把發布Task/urls發布出來,代碼如下:
from datetime import datetime from django.urls import path,re_path,include from django.contrib import admin from django.contrib.auth.views import LoginView, LogoutView from app import forms, views from Task import views as Task_views from Collector import views as Collector_views from Task import urls as task_urls urlpatterns = [ path('', views.home, name='home'), path('contact/', views.contact, name='contact'), path('about/', views.about, name='about'), path('login/', LoginView.as_view ( template_name='app/login.html', authentication_form=forms.BootstrapAuthenticationForm, extra_context= { 'title': 'Log in', 'year' : datetime.now().year, } ), name='login'), path('logout/', LogoutView.as_view(next_page='/'), name='logout'), path('admin/', admin.site.urls), path('admin/tank4C9/', Collector_views.tank4C9), path('getTank4C9Data/', Collector_views.getTank4C9Data), re_path('task/', include(task_urls)), #① ]
文件:IndDemo/urls.py
標注①:新的app urls發布方式,Task采用這種方式在工程中發布url后,后面Task/urls.py增加的url會自動發布,不用每次app增加url都需要去改工程的urls.py文件了。
現在我們工程項目Start server運行我們的工程,然后在瀏覽器鍵入http://localhost:8001/task/查看一下運行結果,會看到hello world! 顯示在瀏覽器上,沒錯還是熟悉的hello world!。
1.2. 顯示靜態任務列表
接下來我們通過html顯示任務列表數據,首先,采用靜態拼字符串的方式來逐步推進編碼的實現,直接反映一個靜態的字符串數據。
from django.shortcuts import render from django.http import HttpResponse def view_list(request): html = "<html><head></head><body><table><tr><th>ID</th><th>任務號</th><th>源地址</th><th>目標地址</th><th>條碼</th><th>狀態</th>"\ + "<th>優先級</th><th>開始時間</th><th>結束時間</th><th>作業數量</th><th>操作</th>"\ + "<tr><td>1</td><td>100</td><td>101</td><td>05-01-01</td><td>101001001008</td>"\ + "<td>處理成功</td><td>正常</td><td>-</td><td>-</td><td>8</td><td>-</td></tr>"\ + "</table></body></html>" return HttpResponse(html)
查看運行結果
初步的效果就出來了,只是現在我們加載的不是數據庫保存的數據,而是硬碼再html文件里數據。
1.3. 動態任務列表
界面要顯示動態的任務列表,就需要我們把數據從數據庫表里抓出來后,采用model數據去拼這個返回html字符串變量,代碼如下:
from django.shortcuts import render from django.http import HttpResponse def view_list(request): html = "<html><head></head><body><table><tr><th>ID</th><th>任務號</th><th>源地址</th><th>目標地址</th><th>條碼</th><th>狀態</th>"\ + "<th>優先級</th><th>開始時間</th><th>結束時間</th><th>作業數量</th><th>操作</th>" tasks = Task.objects.all() for task in tasks: html = html + "<tr><td>"+str(task.TaskId )+ "</td><td>"+str(task.TaskNum)+ "</td><td>"+task.Source+ "</td><td>"+task.Target\ + "</td><td>"+task.Barcode+ "</td><td>"+task.get_State_display()+"</td><td>"+task.get_Priority_display()\ + "</td><td>-</td><td>-</td><td>"+str(task.job_set.count())+"</td><td>-</td></tr>" html = html + "</table></body></html>" return HttpResponse(html)
運行結果
現在客戶端UI能加載到數據庫持久化的任務列表了,從上面的迭代編程過程我們演示是如何采用漸進的方式推進功能的開發,而每一步都能有通過運行的反饋!也就是每一個大目標是由一個一個成功的小目標累積而成的。
隨着功能的增加我們會發現view_list里面的html腳本拼寫會越來越復雜,再繼續采用這種傳統的拼接html腳本的方式效率只會越來越低,維護越來越麻煩。
1.4. 使用django模板重構
代碼重構的定義是再功能不變的前提下,優化和改進代碼的結構!現在我們采用django提供的模板來重構這個頁面,從而把html標記語言與后台數據加載耦合分開,把業務邏輯與界面元數分開。
1.4.1. 靜態模板
代碼如下:
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> </head> <body> <table> <tr> <th>ID</th><th>任務號</th><th>源地址</th><th>目標地址</th><th>條碼</th><th>狀態</th><th>優先級</th><th>開始時間</th><th>結束時間</th><th>作業數量</th><th>操作</th> </tr> <tr> <td>1</td><td>100</td><td>101</td><td>05-01-01</td><td>101001001008</td><td>處理成功</td><td>正常</td><td>-</td><td>-</td><td>8</td><td>-</td> </tr> </table> </body> </html>
文件:Task/templates/tasks.html
修改view_list函數代碼采用模板方式返回請求。
... def view_list(request): return render(request,'Task/tasks.html')
運行結果
1.4.2. 動態模板
接下來把這個模板重構到可以動態加載數據,更多關於django模板的的用法請參閱django的官方文檔。
動態模板代碼:
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title></title> </head> <body> <table> <tr> <th>ID</th> <th>任務號</th> <th>源地址</th> <th>目標地址</th> <th>條碼</th> <th>狀態</th> <th>優先級</th> <th>開始時間</th> <th>結束時間</th> <th>作業數量</th> <th>操作</th> </tr> {% for task in tasks %} <tr> <td>{{task.TaskId }}</td> <td>{{task.TaskNum}}</td> <td>{{task.Source}}</td> <td>{{task.Target}}</td> <td>{{task.Barcode}}</td> <td>{{task.get_State_display}}</td> <td>{{task.get_Priority_display}}</td> <td>-</td> <td>-</td> <td>{{task.job_set.count}}</td> <td>-</td> </tr> {%endfor%} </table> </body> </html>
修改view_list函數,動態加載任務列表。
... def view_list(request): tasks = Task.objects.all() return render(request,'Task/tasks.html',{"tasks":tasks})
運行結果
至此我們采用模板來替換再函數了拼html腳本的方式,你會發現view_list簡潔多了不在包含html相關的內容,通過模板實現了數據加載與html解析過程的解耦合,從而大大的提高了代碼的可讀性和維護擴展能力。
過程我們仍然采用兩步走的方式是進行重構,目的就是演示每一步都有通過運行的反饋,從而讓我們理解采用模板方式(技術)是可行的。對於我們面對不確定的技術和編程新手來說,每一小步的正確推進,也是對掌握這個技術的肯定。
1.5. 小節
編程過程的每一個成功的一小步最終累積成一個完整的功能的編程模式和思路是我們面對不確定性(新技術、新框架、新業務、復雜業務)非常好的一種方式,通過每一小步的成功推進編碼進程,同時及時獲得反饋,運行錯誤反饋讓我們及糾偏,運行正確繼續推進。從而避免走到最后推倒重來的情況。筆者的編程生涯里,身邊無數次發生的讓人抓耳撓腮的實戰案例。