完成 EasyuiCMS on GAE 基本架構之後, 感覺似乎離目標只剩一步之遙, 所以早上就趁著去上一個跟工作幾乎無關的無聊課 (防毒) 時, 把最後一塊拼圖補上, 那就是如何在此架站平台上新增應用服務呢?
在 PHP 版時只要單獨寫好應用程式與其安裝檔兩個檔案, 然後利用檔案上傳就可以自動處理應用程式安裝的所有工作, 安裝後馬上可用. 在 GAE 因為雲端平台架構的關係, 可能比較難做到這樣, 每次新增一個服務必須修改現有檔案並新增相關檔案. 以下便以新增一個工作日誌服務 JLOG 為例, 說明其增修程序.
首先修改資料儲存檔 model.py, 新增一個 Jlogtabs 頁籤的資料模型, 直接從系統的 Hometabs 複製過來改名稱即可 :
class
Jlogtabs(db.Model):
tab_name=db.StringProperty()
tab_label=db.StringProperty()
tab_link=db.StringProperty()
tab_tip=db.StringProperty()
tab_order=db.IntegerProperty()
tab_admin=db.BooleanProperty()
並建立 jlog_home, jlog_knowledge, jlog_admin 三個頁籤的資料實體 :
jlogtab=Jlogtabs(key_name="jlog_home",tab_name="jlog_home",tab_label=u"工作日誌",tab_link="/jlog_home",tab_order=0,tab_admin=
False)
jlogtab.put()
jlogtab=Jlogtabs(key_name="jlog_knowledge",tab_name="jlog_knowledge",tab_label=u"知識庫",tab_link="/jlog_knowledge",tab_order=98,tab_admin=
False)
jlogtab.put()
jlogtab=Jlogtabs(key_name="jlog_admin",tab_name="jlog_admin",
tab_label=u"管理",tab_link="/jlog_admin",tab_order=99,tab_admin=
True)
jlogtab.put()
然後新增一個標頭連結 JLOG 就完成資料庫部分的調整作業了 :
headerlink=Headerlinks(key_name="JLOG",name="JLOG",title=u"JLOG",
url="
javascript:goJLOG()",target="_self",sequence=0,hint=u"JLOG")
headerlink.put()
這裡 url 中的 goJLOG() 函式是要在系統主版面 main.htm 中將工作日誌頁籤網頁載入 panel 的 center 區域, 所以必須到 template/main.htm 中新增此函式 :
function gohome(){
$(function(){
var p=$("body").layout("panel","center");
p.panel({href:"/hometabs"});
});
}
function logout(){
$(function(){
$.messager.confirm("確認","確定要登出系統嗎?",function(btn){
if (btn) {window.location.href="/logout";}
});
});
}
function goJLOG(){
$(function(){
var p=$("body").layout("panel","center");
p.panel({href:"/jlogtabs"});
});
}
事實上就是將 gohome() 複製過來修改即可. 接下來就要去主控程式 main.py 中處理路徑與邏輯. 首先在最底下的 app 中新增上面新增的四個路徑 :
app = webapp2.WSGIApplication([
('/', MainHandler),
('/login', login),
('/check_member', check_member),
('/logout', logout),
('/hometabs', hometabs),
('/home', home),
('/change_theme', change_theme),
('/list_visitors', list_visitors),
('/get_visitors', get_visitors),
('/list_members', list_members),
('/get_members', get_members),
('/remove_visitors', remove_visitors),
('/add_member', add_member),
('/update_member', update_member),
('/remove_member', remove_member),
('/list_headerlinks', list_headerlinks),
('/get_headerlinks', get_headerlinks),
('/add_headerlink', add_headerlink),
('/update_headerlink', update_headerlink),
('/remove_headerlink', remove_headerlink),
('/list_navblocks', list_navblocks),
('/get_navblocks', get_navblocks),
('/add_navblock', add_navblock),
('/update_navblock', update_navblock),
('/remove_navblock', remove_navblock),
('/list_navlinks', list_navlinks),
('/get_navlinks', get_navlinks),
('/add_navlink', add_navlink),
('/update_navlink', update_navlink),
('/remove_navlink', remove_navlink),
('/settings', settings),
('/update_settings', update_settings),
('/member_settings', member_settings),
('/jlogtabs', jlogtabs),
('/jlog_home', jlog_home),
('/jlog_knowledge', jlog_knowledge),
('/jlog_admin', jlog_admin)
], debug=True, config=config)
然後建立四個類別來處理工作日誌的四個路徑, 首先是複製 hometabs 類別來改為 jlogtabs 類別, 然後複製 home 類別來改為 jlog_home, jlog_knowledge, 與 jlog_admin 類別, 分別渲染 hometabs.htm, jlog_home.htm, jlog_knowledge.htm, 以及 jlog_admin.htm 這四個網頁模板 :
class
jlogtabs(BaseHandler):
def get(self):
self.check_login()
jlogtabs=m.
Jlogtabs.all()
jlogtabs.order("tab_order") #sort by tab_order
tabs=[] #for storing tab objects
is_admin=self.session.get('is_admin') #True/False
for t in jlogtabs:
tab={}
tab["tab_label"]=t.tab_label
tab["tab_link"]=t.tab_link
if t.tab_admin: #this tab is for admin only
if is_admin: #current user is admin
tabs.append(tab)
else: #this tab is for registered users
tabs.append(tab)
url="
templates/jlogtabs.htm"
path=os.path.join(os.path.dirname(__file__), url)
content=template.render(path,{"tabs":tabs})
self.response.out.write(content)
class
jlog_home(BaseHandler):
def get(self):
self.check_login()
url="templates/
jlog_home.htm"
path=os.path.join(os.path.dirname(__file__), url)
content=template.render(path,{})
self.response.out.write(content)
class
jlog_knowledge(BaseHandler):
def get(self):
self.check_login()
url="templates/
jlog_knowledge.htm"
path=os.path.join(os.path.dirname(__file__), url)
content=template.render(path,{})
self.response.out.write(content)
class
jlog_admin(BaseHandler):
def get(self):
self.check_login()
url="templates/
jlog_admin.htm"
path=os.path.join(os.path.dirname(__file__), url)
content=template.render(path,{})
self.response.out.write(content)
這樣 main.py 也調整好了, 接下來就是到 /template 目錄下, 複製 hometabs.htm 為 jlogtabs.htm 修改如下 (只改 id 即可) :
<div
id="jlogtabs" class="easyui-tabs" data-options="fit:'true'">
{% for t in tabs %}
<div class="tab" title="{{t.tab_label}}" data-options="href:'{{t.tab_link}}',loadingMessage:'載入中 ... '"></div>
{% endfor %}
</div>
然後複製 home.htm 為 jlog_home.htm, jlog_knowledge.htm, 以及 jlog_admin.htm, 其內容暫時只是文字而已, 例如 jlog_admin.htm 內容為 :
<p>工作日誌管理</p>
OK, 這樣就完成新增應用服務作業了, 上傳雲端主機後按標頭連結 JLOG 即顯示工作日誌頁籤 :
按首頁又會載入 hometabs.htm, 如此即可在多個應用服務之間切換了. 每一個應用服務的入口主要是上面的標頭連結, 當然也可以在左方導覽區另行建立第二入口.
另外, 在新增 JLOG 時也發現標頭連結的排序程式不妥而加以調整, 就是將 main.py 中根目錄處理類別 MainHandler 中的 headerlinks 查詢物件從原先的逆向排序改為正向排序 :
#create param: headerlinks
headerlinks=m.Headerlinks.all()
headerlinks.order("sequence") #sort by sequence
然後把 model.py 中的 headerlink 實體排序如下, 即把系統的首頁與登入 sequence 分別改為 98 與 99, 應用服務則從 0 開始編號, 這樣在正向排序下系統標頭連結會排在最後面 :
headerlink=Headerlinks(key_name="JLOG",name="JLOG",title=u"JLOG",
url="javascript:goJLOG()",target="_self",
sequence=0,hint=u"JLOG")
headerlink.put()
headerlink=Headerlinks(key_name="home",name="home",title=u"首頁",
url="javascript:gohome()",target="_self",
sequence=98,hint=u"首頁")
headerlink.put()
headerlink=Headerlinks(key_name="logout",name="logout",title=u"登出",
url="javascript:logout()",target="_self",
sequence=99,hint=u"登出")
headerlink.put()
這樣這個小專案總算拚完了, 當然安全性上還有待改進 (例如密碼欄位的加密, 以及重設密碼的機制), 但至少可以正常運轉. 完整 zip 檔案可在下列連結下載 :
#
具有 JLOG 應用範例的 EasyuiCMS on GAE