在Django中創(chuàng)建動(dòng)態(tài)視圖的教程
在我們的`` current_datetime`` 視圖范例中,盡管內(nèi)容是動(dòng)態(tài)的,但是URL ( /time/ )是靜態(tài)的。 在 大多數(shù)動(dòng)態(tài)web應(yīng)用程序,URL通常都包含有相關(guān)的參數(shù)。 舉個(gè)例子,一家在線書店會(huì)為每一本書提供一個(gè)URL,如:/books/243/、/books/81196/。
讓我們創(chuàng)建第三個(gè)視圖來顯示當(dāng)前時(shí)間和加上時(shí)間偏差量的時(shí)間,設(shè)計(jì)是這樣的: /time/plus/1/ 顯示當(dāng)前時(shí)間+1個(gè)小時(shí)的頁(yè)面 /time/plus/2/ 顯示當(dāng)前時(shí)間+2個(gè)小時(shí)的頁(yè)面 /time/plus/3/ 顯示當(dāng)前時(shí)間+3個(gè)小時(shí)的頁(yè)面,以此類推。
新手可能會(huì)考慮寫不同的視圖函數(shù)來處理每個(gè)時(shí)間偏差量,URL配置看起來就象這樣:
urlpatterns = patterns('', ('^time/$', current_datetime), ('^time/plus/1/$', one_hour_ahead), ('^time/plus/2/$', two_hours_ahead), ('^time/plus/3/$', three_hours_ahead), ('^time/plus/4/$', four_hours_ahead), )
很明顯,這樣處理是不太妥當(dāng)?shù)摹?不但有很多冗余的視圖函數(shù),而且整個(gè)應(yīng)用也被限制了只支持 預(yù)先定義好的時(shí)間段,2小時(shí),3小時(shí),或者4小時(shí)。 如果哪天我們要實(shí)現(xiàn) 5 小時(shí),我們就 不得不再單獨(dú)創(chuàng)建新的視圖函數(shù)和配置URL,既重復(fù)又混亂。 我們需要在這里做一點(diǎn)抽象,提取 一些共同的東西出來。
關(guān)于漂亮URL的一點(diǎn)建議
如果你有其它web平臺(tái)的開發(fā)經(jīng)驗(yàn)(如PHP或Java),你可能會(huì)想:嘿!讓我們用查詢字符串參數(shù)吧! 就像/time/plus?hours=3里面的小時(shí)應(yīng)該在查詢字符串中被參數(shù)hours指定(問號(hào)后面的是參數(shù))。
你 可以 在Django里也這樣做 (如果你真的想要這樣做,我們稍后會(huì)告訴你怎么做), 但是Django的一個(gè)核心理念就是URL必須看起來漂亮。 URL /time/plus/3/ 更加清晰, 更簡(jiǎn)單,也更有可讀性,可以很容易的大聲念出來,因?yàn)樗羌兾谋荆瑳]有查詢字符串那么 復(fù)雜。 漂亮的URL就像是高質(zhì)量的Web應(yīng)用的一個(gè)標(biāo)志。
Django的URL配置系統(tǒng)可以使你很容易的設(shè)置漂亮的URL,而盡量不要考慮它的 反面 。
那么,我們?nèi)绾卧O(shè)計(jì)程序來處理任意數(shù)量的時(shí)差? 答案是:使用通配符(wildcard URLpatterns)。正如我們之前提到過,一個(gè)URL模式就是一個(gè)正則表達(dá)式。因此,這里可以使用d+來匹配1個(gè)以上的數(shù)字。
urlpatterns = patterns('', # ... (r'^time/plus/\d+/$', hours_ahead), # ... )
這里使用# …來表示省略了其它可能存在的URL模式定義。 這個(gè)URL模式將匹配類似 /time/plus/2/ , /time/plus/25/ ,甚至 /time/plus/100000000000/ 的任何URL。 更進(jìn)一步,讓我們把它限制在最大允許99個(gè)小時(shí), 這樣我們就只允許一個(gè)或兩個(gè)數(shù)字,正則表達(dá)式的語法就是 \d{1,2} :
(r'^time/plus/\d{1,2}/$', hours_ahead),
備注
在建造Web應(yīng)用的時(shí)候,盡可能多考慮可能的數(shù)據(jù)輸入是很重要的,然后決定哪些我們可以接受。 在這里我們就設(shè)置了99個(gè)小時(shí)的時(shí)間段限制。
另外一個(gè)重點(diǎn),正則表達(dá)式字符串的開頭字母“r”。 它告訴Python這是個(gè)原始字符串,不需要處理里面的反斜杠(轉(zhuǎn)義字符)。 在普通Python字符串中,反斜杠用于特殊字符的轉(zhuǎn)義。比如n轉(zhuǎn)義成一個(gè)換行符。 當(dāng)你用r把它標(biāo)示為一個(gè)原始字符串后,Python不再視其中的反斜杠為轉(zhuǎn)義字符。也就是說,“n”是兩個(gè)字符串:“”和“n”。由于反斜杠在Python代碼和正則表達(dá)式中有沖突,因此建議你在Python定義正則表達(dá)式時(shí)都使用原始字符串。 從現(xiàn)在開始,本文所有URL模式都用原始字符串。
現(xiàn)在我們已經(jīng)設(shè)計(jì)了一個(gè)帶通配符的URL,我們需要一個(gè)方法把它傳遞到視圖函數(shù)里去,這樣 我們只用一個(gè)視圖函數(shù)就可以處理所有的時(shí)間段了。 我們使用圓括號(hào)把參數(shù)在URL模式里標(biāo)識(shí) 出來。 在這個(gè)例子中,我們想要把這些數(shù)字作為參數(shù),用圓括號(hào)把 \d{1,2} 包圍起來:
(r'^time/plus/(\d{1,2})/$', hours_ahead),
如果你熟悉正則表達(dá)式,那么你應(yīng)該已經(jīng)了解,正則表達(dá)式也是用圓括號(hào)來從文本里 提取 數(shù)據(jù)的。
最終的URLconf包含上面兩個(gè)視圖,如:
from django.conf.urls.defaults import * from mysite.views import hello, current_datetime, hours_ahead urlpatterns = patterns('', (r'^hello/$', hello), (r'^time/$', current_datetime), (r'^time/plus/(\d{1,2})/$', hours_ahead), )
現(xiàn)在開始寫 hours_ahead 視圖。
編碼次序
這個(gè)例子中,我們先寫了URLpattern ,然后是視圖,但是在前面的例子中, 我們先寫了視圖,然后是URLpattern 。 哪一種方式比較好?
嗯,怎么說呢,每個(gè)開發(fā)者是不一樣的。
如果你是喜歡從總體上來把握事物(注: 或譯為“大局觀”)類型的人,你應(yīng)該會(huì)想在項(xiàng)目開始 的時(shí)候就寫下所有的URL配置。
如果你從更像是一個(gè)自底向上的開發(fā)者,你可能更喜歡先寫視圖, 然后把它們掛接到URL上。 這同樣是可以的。
最后,取決與你喜歡哪種技術(shù),兩種方法都是可以的。 (見上)
hours_ahead 和我們以前寫的 current_datetime 很象,關(guān)鍵的區(qū)別在于: 它多了一個(gè)額外參數(shù),時(shí)間差。 以下是view代碼:
from django.http import Http404, HttpResponse import datetime def hours_ahead(request, offset): try: offset = int(offset) except ValueError: raise Http404() dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) return HttpResponse(html)
讓我們逐行分析一下代碼:
視圖函數(shù), hours_ahead , 有 兩個(gè) 參數(shù): request 和 offset . (見上)
request 是一個(gè) HttpRequest 對(duì)象, 就像在 current_datetime 中一樣. 再說一次好了: 每一個(gè)視圖 總是 以一個(gè) HttpRequest 對(duì)象作為 它的第一個(gè)參數(shù)。 (見上)
offset 是從匹配的URL里提取出來的。 例如:如果請(qǐng)求URL是/time/plus/3/,那么offset將會(huì)是3;如果請(qǐng)求URL是/time/plus/21/,那么offset將會(huì)是21。請(qǐng)注意:捕獲值永遠(yuǎn)都是字符串(string)類型,而不會(huì)是整數(shù)(integer)類型,即使這個(gè)字符串全由數(shù)字構(gòu)成(如:“21”)。
(從技術(shù)上來說,捕獲值總是Unicode objects,而不是簡(jiǎn)單的Python字節(jié)串,但目前不需要擔(dān)心這些差別。)
在這里我們命名變量為 offset ,你也可以任意命名它,只要符合Python 的語法。 變量名是無關(guān)緊要的,重要的是它的位置,它是這個(gè)函數(shù)的第二個(gè) 參數(shù) (在 request 的后面)。 你還可以使用關(guān)鍵字來定義它,而不是用 位置。
我們?cè)谶@個(gè)函數(shù)中要做的第一件事情就是在 offset 上調(diào)用 int() . 這會(huì)把這個(gè)字符串值轉(zhuǎn)換為整數(shù)。
請(qǐng)留意:如果你在一個(gè)不能轉(zhuǎn)換成整數(shù)類型的值上調(diào)用int(),Python將拋出一個(gè)ValueError異常。如:int(‘foo')。在這個(gè)例子中,如果我們遇到ValueError異常,我們將轉(zhuǎn)為拋出django.http.Http404異?!缒阆胂蟮哪菢樱鹤罱K顯示404頁(yè)面(提示信息:頁(yè)面不存在)。
機(jī)靈的讀者可能會(huì)問: 我們?cè)赨RL模式中用正則表達(dá)式(d{1,2})約束它,僅接受數(shù)字怎么樣?這樣無論如何,offset都是由數(shù)字構(gòu)成的。 答案是:我們不會(huì)這么做,因?yàn)閁RLpattern提供的是“適度但有用”級(jí)別的輸入校驗(yàn)。萬一這個(gè)視圖函數(shù)被其它方式調(diào)用,我們?nèi)孕枳孕袡z查ValueError。 實(shí)踐證明,在實(shí)現(xiàn)視圖函數(shù)時(shí),不臆測(cè)參數(shù)值的做法是比較好的。 松散耦合,還記得么?
下一行,計(jì)算當(dāng)前日期/時(shí)間,然后加上適當(dāng)?shù)男r(shí)數(shù)。 在current_datetime視圖中,我們已經(jīng)見過datetime.datetime.now()。這里新的概念是執(zhí)行日期/時(shí)間的算術(shù)操作。我們需要?jiǎng)?chuàng)建一個(gè)datetime.timedelta對(duì)象和增加一個(gè)datetime.datetime對(duì)象。 結(jié)果保存在變量dt中。
這一行還說明了,我們?yōu)槭裁丛趏ffset上調(diào)用int()——datetime.timedelta函數(shù)要求hours參數(shù)必須為整數(shù)類型。
這行和前面的那行的的一個(gè)微小差別就是,它使用帶有兩個(gè)值的Python的格式化字符串功能, 而不僅僅是一個(gè)值。 因此,在字符串中有兩個(gè) %s 符號(hào)和一個(gè)以進(jìn)行插入的值的元組: (offset, dt) 。
最終,返回一個(gè)HTML的HttpResponse。 如今,這種方式已經(jīng)過時(shí)了。
在完成視圖函數(shù)和URL配置編寫后,啟動(dòng)Django開發(fā)服務(wù)器,用瀏覽器訪問 http://127.0.0.1:8000/time/plus/3/ 來確認(rèn)它工作正常。 然后是 http://127.0.0.1:8000/time/plus/5/ 。再然后是 http://127.0.0.1:8000/time/plus/24/ 。最后,訪問 http://127.0.0.1:8000/time/plus/100/ 來檢驗(yàn)URL配置里設(shè)置的模式是否只 接受一個(gè)或兩個(gè)數(shù)字;Django會(huì)顯示一個(gè) Page not found error 頁(yè)面, 和以前看到的 404 錯(cuò)誤一樣。 訪問URL http://127.0.0.1:8000/time/plus/ (沒有 定義時(shí)間差) 也會(huì)拋出404錯(cuò)誤。
相關(guān)文章
Python 內(nèi)置函數(shù)complex詳解
這篇文章主要介紹了Python 內(nèi)置函數(shù)complex詳解的相關(guān)資料,需要的朋友可以參考下2016-10-10用python打開攝像頭并把圖像傳回qq郵箱(Pyinstaller打包)
這篇文章主要介紹了用python打開攝像頭并把圖像傳回qq郵箱,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Python+matplotlib實(shí)現(xiàn)循環(huán)作圖的方法詳解
這篇文章主要為大家介紹了Python如何利用matplotlib實(shí)現(xiàn)循環(huán)作圖的,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)2022-06-06np.mean()和np.std()函數(shù)的具體使用
本文主要介紹了np.mean()和np.std()函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03利用python+request通過接口實(shí)現(xiàn)人員通行記錄上傳功能
這篇文章主要介紹了利用python+request通過接口實(shí)現(xiàn)人員通行記錄上傳功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01