跳轉到內容

Karrigell/主頁

來自華夏公益教科書,為開放世界提供開放書籍

目前,我們將忽略 CD 並開始編寫主頁

建立一個新資料夾mycds在您的 Karrigell 發行版中,位於www資料夾下。使用您喜歡的文字編輯器,將此文字儲存到名為index.ks

def index():
    print "<h1>My CD collection</h1>"

在您的瀏覽器中,訪問localhost/mycds/index.ks/index

副檔名 "ks" (Karrigell 服務) 表示該指令碼是 Python 指令碼,其中函式與 URL 匹配:這裡,index.ks/index表示該函式index()將把資料傳送回瀏覽器

事實上

  • 如果您沒有指定函式名,則指令碼中的index()函式將被執行,因此您可以訪問localhost/mycds/index.ks
  • 而且,如果您在一個資料夾中甚至沒有指定指令碼名,則名為index的指令碼將被執行。所以您實際上只需要輸入localhost/mycds

請注意print語句在index()函式中。在 Karrigell 指令碼中,print語句將內容傳送到瀏覽器;預設情況下,此內容應該是 HTML 程式碼

新增頁面計數器

[編輯 | 編輯原始碼]

頁面計數器將列印頁面被訪問的次數。我們將使用一個檔案,counter.txt,來儲存訪問次數併為每次訪問遞增。

def index():
    print "<h1>My CD collection</h1>"
    try:
        visits = int(open('counter.txt').read())
    except IOError:
        # first visit : the file does not exist
        visits = 0
    visits += 1
    out = open('counter.txt','w')
    out.write(str(visits))
    out.close()
    print "%s visits" %visits

每次頁面重新載入時,您都會看到訪問次數增加 1。

請注意,該檔案透過通常的open()函式開啟;相對路徑相對於指令碼目錄轉換為絕對路徑。

一個更好的頁面計數器

[編輯 | 編輯原始碼]

如果同一個使用者反覆重新載入同一個頁面,頁面計數器不應遞增。這需要一種識別傳送請求的瀏覽器的方法。為了完成此任務,網頁程式設計提供了會話管理,而 Karrigell 對此概念有非常簡單的實現。

使用內建的Session()函式

Karrigell 指令碼在由框架準備的名稱空間中執行:在指令碼中可用的名稱中,您擁有此Session()函式,它返回特定於每個單個客戶端的物件(它使用 cookie)。此物件是一個普通的 Python 物件,您可以為其設定任何您喜歡的屬性。

這裡,對於新客戶端,我們將為會話物件建立一個名為 user 的屬性。如果客戶端請求主頁,並且他的會話物件已經擁有此屬性,則計數器將不會遞增。

def index():
    print "<h1>My CD collection</h1>"
    try:
        visits = int(open('counter.txt').read())
    except IOError:
        # first visit : the file does not exist
        visits = 0
    if not hasattr(Session(),"user"):
        visits += 1
        out = open('counter.txt','w')
        out.write(str(visits))
        out.close()
        Session().user = None    # create attribute user
    print "%s visits" %visits

包含指令碼

[編輯 | 編輯原始碼]

此頁面計數器可以在應用程式的其他部分使用,因此最好將其放在單獨的檔案中:將指令碼的這一部分儲存到counter.py

try:
    visits = int(open('counter.txt').read())
except IOError:
    # first visit : the file does not exist
    visits = 0
    if not hasattr(Session(),"user"):
    visits += 1
    out = open('counter.txt','w')
    out.write(str(visits))
    out.close()
    Session().user = None   # create attribute user
print "%s visits" %visits

中。index.ks要將此指令碼包含在主頁中,請更改指令碼

def index():
    print "<h1>My CD collection>/h1>"
    Include('counter.py')

為以下內容:Include() 是另一個 Karrigell 內建函式:它接受一個指令碼 URL 作為引數,並將此指令碼執行的結果插入頁面。

為了使counter.py更加模組化,檔名可以作為引數傳遞給為以下內容:

def index():
    print "<h1>My CD collection>/h1>"
    Include('counter.py',counter_file='counter.txt')

為以下內容:的關鍵字引數將在counter.py執行時位於執行名稱空間中。用以下引數改寫counter.py

try:
    visits = int(open(counter_file).read())
except IOError:
    # first visit : the file does not exist
    visits = 0
if not hasattr(Session(),"user"):
    visits += 1
    out = open(counter_file,'w')
    out.write(str(visits))
    out.close()
    Session().user = None   # create attribute user
print "%s visits" %visits

登入/退出

[編輯 | 編輯原始碼]

讓我們新增一個連結供使用者登入應用程式。

def index():
    print "<h1>My CD collection</h1>"
    print '<a href="login">Login</a><br>'
    Include('../counter.py',counter_file='counter.txt')

該連結指向引用"login"。它是一個相對於基本 URL 的相對 URL,host/records/index.ks/index,因此它解析為host/records/index.ks/login,這意味著該連結將呼叫指令碼中login()函式的執行。index.ks

此函式將生成一個 HTML 表單,要求使用者輸入登入名和密碼,並將這些值提交給身份驗證測試。

def login():
    print '<h1>Login</h1>'
    print '<form action="check_login" method="post">'
    print 'Login <input name="login"><br>'
    print 'Password <input type="password" name="passwd"><br>'
    print '<input type="submit" value="Ok">'
    print '</form>'

表單的屬性"action"check_login。同樣,這意味著check_login()函式將在index.ks中執行。

index()login()不同,此函式將接受引數:提交的登入名和密碼。引數必須與表單的輸入欄位中使用的名稱相同:loginpasswd。目前,我們將使用一個非常簡單的測試來檢視使用者是否被允許登入。

def check_login(login,passwd):
    if login=="john" and passwd=="doe":
        Session().user = login
        print "logged in"
    else:
        print "try again"

在此函式內部,如果測試成功,則會話物件的屬性user將設定為使用者的登入名。

目前,我們只有測試結果。測試後,我們應該自動返回主頁。HTTP 協議提供了重定向功能,而 Karrigell 的實現再次非常簡單:一個名為HTTP_REDIRECTION

的內建異常。check_login()將函式更改為以下內容:

def check_login(login,passwd):
    if login=="john" and passwd=="doe":
        Session().user = login
    raise HTTP_REDIRECTION,"index"

這意味著在函式執行後,瀏覽器將重定向到指定的 URL,這裡是指與函式index()函式的執行。

匹配的 URL。

def index():
    print "<h1>My CD collection</h1>"
    logged = hasattr(Session(),"user") and Session().user is not None
    if logged:
        print 'Logged in as %s<br>' %Session().user
        print '<a href="logout">Logout</a><br>'
    else:
        print '<a href="login">Login</a><br>'
    Include('../counter.py',counter_file='counter.txt')

我們現在可以更改主頁,以使用使用者的姓名歡迎經過身份驗證的使用者,並允許他登出。登出函式將只設置Session().userNone

def logout():
    del Session().user
    raise HTTP_REDIRECTION,"index"

並重定向到主頁。

總結

[編輯 | 編輯原始碼]Session()Karrigell 使用的程式設計風格基於名稱空間:在指令碼中,不匯入模組或使用環境變數,而是提供了一些內建名稱供最常見的任務使用。到目前為止,我們已經涵蓋了使用內建名稱為以下內容:的會話管理,使用HTTP_REDIRECTION

包含指令碼,以及使用內建異常

進行 HTTP 重定向。這使得使用 Karrigell 進行程式設計非常簡單,因此易於編碼和維護。

雖然有其他格式可用(有關純 Python 指令碼、CGI、Python Inside HTML、HTML Inside Python 的文件,請參閱文件),但我建議使用 "Karrigell 服務" 將大部分應用程式邏輯組合在一個指令碼中;外圍模組可以被匯入或包含。

下一節中,我們將編寫用於管理 CD 資料庫的程式碼。
華夏公益教科書