「D」不發音html
文中全部交互的部分都是在 python manage.py shell 下執行的,python
將數據驅動的 web 應用按數據存取邏輯、表現邏輯和業務邏輯劃分結構的一種概念被稱爲 Model-View-Controller 模式(MVC)。這種模式在 Django 上的體現即是 MTV 模式,分別爲負責數據庫業務的 Model、負責頁面表現的 Template 和負責組織業務的 View。web
Project 能夠看作是包含了用於建立和運行整個網站的全部文件的一個文件夾,而 app 則是 project 下一級目錄內的多個子文件夾,每一個 app 都包含有獨立的功能,apps 的總體組成了整個網站。嘛,大約能夠看作是「對象」和「方法」的關係吧。正則表達式
建立 project 可使用命令行:django-admin.py startproject site_nameshell
django-admin.py 位於 Python 安裝目錄下的 Sripts 文件夾。這條命令會在執行目錄下建立一個文件夾,文件夾內包含一個項目管理文件 manage.py 和一個與「site_name」同名的子文件夾,該文件夾內默認包含 __init__.py , settings.py , urls.py , wsgi.py 四個項目配置文件。數據庫
使用 manage.py 建立 app 後,appname 文件夾裏面初始包含五個文件,__inti__.py 的功能與上面同樣,其餘爲:django
視圖函數包含於項目文件夾和 apps 文件夾的 views 文件內。每個函數能夠處理一類業務,並返回一個相應頁面。瀏覽器
對「什麼樣的 url 地址調用什麼樣的函數」的問題,則配置於項目文件夾內的 urls 文件內。urls 的 urlpatterns 變量在建立的時候就帶有兩條被註釋起來的樣例,以提醒 patterns 對象的標準語法:app
urlpatterns = patterns( '' , # Examples: # url(r'^$', 'mysite.views.home', name='home'), # url(r'^blog/', include('blog.urls')), )
能夠看到 patterns 對象的第一個參數是一個空字符串 '' ,這實際上是一個公共視圖前綴,將加在後面的每個字符串函數路徑的前面。函數
同時,爲了對應存在多個不一樣的視圖前綴的狀況,好比給每個 app 使用一個公共視圖前綴,urlpatterns 對象是能夠自加的( += ):
urlpatterns = patterns( ' app1.views ' , url(r ' ^app1_url$ ' , ' func_in_app1 ' ) ) urlpatterns += patterns( ' app2.views ' , url(r ' ^app2_url$ ' , ' func_in_app2 ' ) )
url 參數可由 urlpattern 以正則表達式的形式捕獲,並自動傳入視圖函數。捕獲方式與「子組」相似,使用 ( ) 來完成:
urlpatterns = patterns( '' , (r ' ^(\d{1,2})/$ ' , ' app.views.func ' ), )
這裏的 (\d{1,2}) 會匹配一個一到兩位的數字,並以字符串的形式傳入視圖函數,這類參數老是以字符串的形式傳入。
另外在視圖函數中,也應當作好參數類型檢查,應當老是認爲調用者是不可靠的。
除了使用 ( ) 捕獲位置參數的方式外,還可使用一種 (?P<name>pattern) 的形式捕獲關鍵字參數 name=pattern:
urlpatterns = patterns( '' , url(r ' ^articles/(?P<year>\d{4})/$ ' , views.year_archive), url(r ' ^articles/(?P<year>\d{4})/(?P<month>\d{2})/$ ' , views.month_archive), )
雖然前面都沒寫,但 url 構造器其實還有可選的第三個參數—— 字典封裝的關鍵字參數:
urlpatterns = patterns( '' , url(r ' ^foo/$ ' , views.foobar_view, { ' template_name ' : ' template1.html ' }), url(r ' ^bar/$ ' , views.foobar_view, { ' template_name ' : ' template2.html ' }), ) # views def foobar_view(request, template_name): m_list = MyModel.objects.filter(is_new = True) return render_to_response(template_name, { ' m_list ' : m_list})
1. 僞造捕捉到的 URLConf 值
若是某個視圖函數定義了一些 url 參數,而你又想在一個沒法提供完整參數的 url 下使用這個視圖,那麼你可使用額外的參數來補完它。
2. 建立一個通用視圖
待續...
3. 優先級問題
當捕捉到的命名組變量和額外參數發生衝突的時候,額外參數優先
當某種匹配模式有特殊狀況,須要爲其調用其餘視圖函數時,能夠經過將這個特殊模式添加到 URLConf 的首位的方式來實現,由於 Django 對 urlpatterns 的解析是順序的。
在最上面提到的,urls 文件內自帶的兩條註釋起來的示例中,就有一個 include 的例子:
urlpatterns = patterns( '' , # Examples: # url(r'^$', 'mysite.views.home', name='home'), # url(r'^blog/', include('blog.urls')), )
能夠看到他的特別之處在於:首先,url 表達式的結尾沒有 $ ,而是一條 / ;其次,視圖函數的地方換成了一個 include。
這個 include 的做用是引入了另外一個 urls 文件。或者更確切的說,他會把已經匹配的部分截斷,而後將剩餘的 url 表達式傳入 include 指向的 urls 文件內去匹配。這個功能相似於公共視圖前綴,不過實現的方式不一樣,include 更適用於必須在多個位置配置不一樣 urls 文件的狀況,或者直接使用已配置好的 urls 文件的狀況(好比 admin 頁面)。
注意:若是在使用 include 的時候,在父 URLConf 中捕獲了參數,那麼這個參數會被傳入子 URLConf 中,子 URLConf 必須對此做出正確響應,不然會引起參數異常。這點對於額外的參數也是同樣的。
視圖函數的任務簡單來講就是解析一個 HttpRequest 對象,而後返回一個 HttpResponse 對象。一個最簡單的視圖函數(什麼也不作)看起來像是這樣子的:
def foo(request): return HttpResponse( "" )
request 對象老是做爲第一個參數傳進來。
當大量視圖函數有一些功能獨立的公共代碼時,能夠把這些代碼寫成裝飾器函數,並在定義視圖函數時使用。好比下面登陸認證的例子:
def requires_login(view): def new_view(request, * args, ** kwargs): if not request.user.is_authenticated(): return HttpResponseRedirect( ' /accounts/login/ ' ) return view(request, * args, ** kwargs) return new_view
request 對象包含的當前請求 url 的一些信息:
request.META 是一個 Python字典,包含了本次 HTTP 請求的 Header 信息。裏面常見的鍵有:
應當使用 request.META.get() 方法來獲取鍵的值,這樣能夠避免鍵不存在時引起的異常。
request 還有 GET 和 POST 屬性,他們都是類字典對象,都有 get() , keys() , values() 方法。
使用 Form 類的通常方法是在 app 路徑內新建一個 forms.py,在其中爲模板的每一個 <form> 元素創建一個對應的類。
from django import forms class ContactForm(forms.Form): subject = forms.CharField() email = forms.EmailField(required = False) message = forms.CharField()
其中 required=False 表示這個字段是可選項。
使用 print() 函數能夠以 html 的形式顯示實例化的表單對象,默認使用<table>標籤,但也能夠用<ul>和<form>標籤顯示。不過這三種標籤最外層的開閉合標記並無顯示出來,以便於編輯其內容:
>>> from contact.forms import ContactForm >>> f = ContactForm() >>> print f < tr >< th >< label for = " id_subject " > Subject: </ label ></ th >< td >< input type = " text " name = " subject " id = " id_subject " /></ td ></ tr > < tr >< th >< label for = " id_email " > Email: </ label ></ th >< td >< input type = " text " name = " email " id = " id_email " /></ td ></ tr > < tr >< th >< label for = " id_message " > Message: </ label ></ th >< td >< input type = " text " name = " message " id = " id_message " /></ td > >>> print f.as_ul() < li >< label for = " id_subject " > Subject: </ label > < input type = " text " name = " subject " id = " id_subject " /></ li > < li >< label for = " id_email " > Email: </ label > < input type = " text " name = " email " id = " id_email " /></ li > < li >< label for = " id_message " > Message: </ label > < input type = " text " name = " message " id = " id_message " /></ li > >>> print f.as_p() < p >< label for = " id_subject " > Subject: </ label > < input type = " text " name = " subject " id = " id_subject " /></ p > < p >< label for = " id_email " > Email: </ label > < input type = " text " name = " email " id = " id_email " /></ p > < p >< label for = " id_message " > Message: </ label > < input type = " text " name = " message " id = " id_message " /></ p >
在實例化 Form 對象的時候,若是傳入對應的字典,就能夠獲得一個綁定的 Form 對象
>>> f = ContactForm({ ' subject ' : ' Hello ' , ' email ' : ' adrian@example.com ' , ' message ' : ' Nice site! ' }) >>> f.is_bound True
綁定對象都有 is_valid() 方法
>>> f.is_valid() True
相應的也就有一個 errors 屬性,這是一個字段名與其錯誤信息相對應的字典:
>>> f = ContactForm({ ' subject ' : ' Hello ' , ' message ' : '' }) >>> f.errors { ' message ' : [u ' This field is required. ' ]}
最後,若是一個綁定 Form 對象是有效的,那麼它就會有一個 cleaned_data 屬性,cleaned_data 字典裏的值都是 Python 的數據類型:
>>> f.cleaned_data { ' message ' : ' Nice site! ' , ' email ' : ' adrian@example.com ' , ' subject ' : ' Hello ' }
def contact(request): if request.method == ' POST ' : form = ContactForm(request.POST) if form.is_valid(): cd = form.cleaned_data . . . return HttpResponseRedirect( ' /contact/thanks/ ' ) else : form = ContactForm() return render_to_response( ' contact_form.html ' , { ' form ' : form})
整個交互工做都是基於 Form 的。
from django import forms class ContactForm(forms.Form): subject = forms.CharField(max_length = 100 ) email = forms.EmailField(required = False) message = forms.CharField(widget = forms.Textarea)
選項min_length參數一樣可用。
from django import forms class ContactForm(forms.Form): subject = forms.CharField(max_length = 100 ) email = forms.EmailField(required = False) message = forms.CharField(widget = forms.Textarea) def clean_message(self): message = self.cleaned_data[ ' message ' ] num_words = len(message.split()) if num_words < 4 : raise forms.ValidationError( " Not enough words! " ) return message
Django的form系統自動尋找匹配的函數方法,該方法名稱以clean_開頭,並以字段名稱結束。 若是有這樣的方法,它將在校驗時被調用。特別地,clean_message()方法將在指定字段的默認校驗邏輯執行以後被調用。