轉載請註明來源地址和原做者(CFishHome)正則表達式
上一節的學前準備工做和第一個小牛試刀的Django項目學習,讓咱們對Django開發愈來愈感興趣了。正所謂趁熱打鐵,讓咱們繼續來學習網站開發必備的視圖函數和URL映射等知識,跟着步伐一塊兒學習,我相信你會收穫不少。噔~噔,新聞播報時間:9月12-9月16有兩個超強颱風在廣東湛江登錄,沿途影響衆多城市,包括深圳!!因此很遺憾,前幾天打算和舍友去深圳遊玩的計劃泡湯了,也只能推遲幾天前往深圳度中秋、看月亮了~算法
不管是使用命令行仍是Pycharm建立Django項目工程,settings.py文件的DEBUG都默認設置爲True,因此默認是開啓了DEBUG模式。以下圖所示:
開啓DEBUG模式有如下好處:
1.咱們能夠發現,在Django開發時,頻繁修改文件代碼,而後要關閉項目,再重啓項目才能測試咱們修改的代碼。可是若是開啓了DEBUG模式,那麼之後咱們修改了Django項目的代碼,而後按下了ctrl+s,那麼Django就會自動的給咱們重啓項目,不須要手動關閉再重啓。
2.若是開啓了DEBUG模式,那麼之後Django項目中的代碼出現bug了,那麼在瀏覽器和控制檯會打印出錯信息。
3.在實際將項目發佈到網上給其餘用戶使用時,禁止開啓DEBUG模式,由於前面說了入宮出現bug會在瀏覽器和控制檯打印出錯信息,這無疑把代碼泄露在網上,會有很大的安全隱患。
4.若是DEBUG設置爲False,那麼必須設置ALLOWED_HOSTS。前一篇說過,若是將host設置爲0.0.0.0,那麼只能經過ALLOWED_HOSTS設置的IP地址進行訪問該項目,也能夠設置多個IP地址。ALLOWED_HOSTS字段以下圖位置:數據庫
咱們在學習前先回顧下咱們上一篇作了什麼。上一篇咱們首先在Pycharm建立了一個名爲first_project的Django項目,而後在CMD使用命令建立了一個名爲my_app的app應用。注意,上篇因測試須要修改了IP地址和端口號,因此這裏我將項目的IP地址和端口號修改回127.0.0.1:8000,說明訪問這個IP就能夠訪問咱們的項目了。總體框架以下圖所示:django
視圖其實就是視圖函數,它通常都寫在 app 的 views.py 文件中,也就是咱們my_app包裏的views.py文件。而且視圖函數的第一個參數永遠都是 request (一個HttpRequest)對象。這個對象存儲了請求過來的全部信息,包括攜帶的參數以及一些頭部信息等。在視圖中,通常是完成邏輯相關的操做。好比這個請求是添加一篇博客,那麼在視圖函數能夠經過request來接收到這些數據,而後存儲到數據庫中,最後再把函數執行的結果返回給瀏覽器。視圖函數的返回結果必須是 HttpResponseBase 對象或者子類的對象。
咱們打開my_app的views.py文件,添加如下代碼:編程
from django.http import HttpResponse # book_list是咱們定義的一個視圖函數,第一個參數必須是request對象,而且該函數返回必須是 HttpResponseBase 對象或者子類的對象。 def book_list(request): return HttpResponse("書籍列表!")
上面視圖函數返回的 HttpResponse("書籍列表!")只是單純的在網頁上輸出"書籍列表!"文本內容。瀏覽器
視圖函數寫完後,咱們怎麼實現讓用戶在瀏覽器中輸入一個URL就能夠訪問到咱們剛纔寫的視圖函數,即用戶在瀏覽器一輸入某URL,網頁就顯示"書籍列表!"文本內容。安全
URL映射原理:用戶在瀏覽器輸入了某個 URL ,請求到咱們的網站的時候, django 會從項目的 urls.py 文件中尋找對應的視圖。爲何會是在urls.py文件中尋找映射呢?這是由於在"settings.py"文件中配置了"ROT_URLCONF"爲"urls.py"。在 urls.py 文件中有一個 urlpatterns 變量,之後 django 就會從這個變量中讀取全部的匹配規則。匹配規則須要使用 django.urls.path 函數進行包裹,這個函數會根據傳入的參數返回 URLPattern 或者是 URLResolver 的對象。app
修改first_project項目的 urls.py 文件代碼,示例代碼以下:框架
from django.contrib import admin from django.urls import path from my_app import views # 導入my_app包的views.py模塊 urlpatterns = [ path('admin/', admin.site.urls), path('book/', views.book_list) ]
運行first_project項目,在瀏覽器輸入127.0.0.1:8000/book,訪問成功!以下圖所示(圖片左下角顯示了"書籍列表!"文本內容):
到了這裏朋友們可能會好奇若是輸入127.0.0.1:8000會怎麼樣?知足你的好奇心,結果以下:
個人天!我按照上一篇的流程能夠訪問的啊,怎麼如今不彳亍了。其實當新添加了第一個URL映射以後須要注意的是主網頁127.0.0.1:8000的網頁404丟失了,這是由於若是剛開始建立的項目,若還未添加過URL映射,那麼默認Django的底層提供一個就是那個火箭??頁面來映射,但若添加了,那麼就沒法繼續映射那個火箭??頁面了,由於看urlpatterns變量其實都沒有映射空URL,即127.0.0.1:8000爲空URL。編程語言
爲URL傳遞參數有三種方式:
1.URL中添加參數
2.查詢字符串傳遞參數
3.指定默認的參數
有時候, url 中包含了一些參數須要動態調整。好比簡書某篇文章的詳情頁的url,是 https://www.jianshu.com/p/a5aab9c4978e 後面的 a5aab9c4978e 就是這篇文章的 id ,那麼簡書的文章詳情頁面的url就能夠寫成 https://www.jianshu.com/p/<id>; ,其中id就是文章的id。那麼如何在 django 中實現這種需求呢。這時候咱們能夠在 path 函數中,使用尖括號的形式來定義一個參數,也能夠多個參數。好比我如今想要獲取一本書籍的詳細信息,那麼應該在 url 中指定這個參數。first_project項目urls.py文件的示例代碼以下:
from django.contrib import admin from django.urls import path from book import views urlpatterns = [ path('admin/', admin.site.urls), path('book/',views.book_list), path('book/<book_id>/',views.book_detail) # <book_id>就是參數 ]
採用在URL中使用變量的方式,在path函數的第一個參數中,使用「<參數名>」的方式能夠傳遞參數,而後在視圖函數中也要寫一個函數來進行映射,視圖函數中的參數必須和URL中的參數名稱保持一致,否則就找不到這個參數(視圖函數第一個參數是request,那麼第二個參數就是book_id)。
而my_app包的views.py 中的代碼以下:
# 該視圖函數與'book/<book_id>/'進行URL映射,而且視圖函數第二個參數必須同名 def book_detail(request,book_id): text = "您輸入的書籍的id是:%s" % book_id return HttpResponse(text)
運行結果以下:
對於多個參數也一樣相似,這裏再也不測試。只不過在URL中添加多個參數,而後視圖函數添加多個同名參數來接收。
另外一種方式是經過查詢字符串的方式傳遞一個參數過去。在設置URL時,不須要單獨的匹配查詢字符串的部分,只須要在視圖函數中使用request.GET.get('參數名稱')的方式來獲取。由於查詢字符串使用的是「GET」請求,因此咱們經過「request.GET」來獲取參數。
first_project項目的urls.py文件的示例代碼以下:
urlpatterns = [ path('admin/', admin.site.urls), path('book/',views.book_list), path('book/<int:book_id>/',views.book_detail), # <book_id>就是參數,注意book_id前面還添加了個int轉換器,這裏只要咱們知道這是限制輸入的id只能是整型便可,後面會詳細講解轉換器的做用。 path('book/pub/',views.book_pub) ]
在 my_app包中的views.py 後面添加以下代碼:
def book_pub(request): pub_id = request.GET.get("id") text = "您輸入的出版社id是:%s" % pub_id return HttpResponse(text)
之後在瀏覽器輸入127.0.0.1:8000/book/pub/?id=1 便可將參數傳遞過去。
運行結果以下:
咱們作個小測試,若是將轉換器Int去掉的話,咱們還能成功訪問到嘛?將urls.py文件代碼修改以下:
urlpatterns = [ path('admin/', admin.site.urls), path('book/',views.book_list), path('book/<book_id>/',views.book_detail), path('book/pub/',views.book_pub) ]
運行結果以下:
經過上圖能夠發現,跟咱們預期的不太同樣,咱們在瀏覽器輸入的URL(http://127.0.0.1:8000/book/pub/?id=200) 被book_detail視圖函數捕獲了,這說明pub後面的全部字符串都被認爲是傳遞到book_detail視圖函數。
使用 path 後,在path的第一個參數能夠包含參數,而有時候想指定默認的參數,這時候能夠經過如下方式來完成,如下代碼僅供理解默認參數的使用,在咱們的實際項目中沒有此代碼。
from django.urls import path from . import views urlpatterns = [ path('blog/', views.page), path('blog/page<int:num>/', views.page), ] # View (in blog/views.py) def page(request, num=1): # Output the appropriate page of blog entries, according to num.
上面'blog/page<int:num>/',參數前面多了個page,表明輸入URL時須要添加page,例如:’127.0.0.1:8000/blog/page100‘。所欲,若是你只寫’127.0.0.1:8000/blog/page',那麼將使用默認參數,num值爲1。
默認參數的使用規則以下:
1.當用戶訪問一個URL不含有變量的時候,映射到視圖函數
而且視圖函數的形參有一個默認參數含有值,視圖函數就直
接使用這個默認參數。
2.當用戶訪問一個URL含有變量的時候,映射到視圖函數並
且視圖函數的形參有一個默認參數含有值,視圖函數就不使
用默認參數的值,而是採用URL匹配規則傳進來的值。
總結:其實上面的默認函數使用規則和編程語言函數的默認
參數使用規則相似。
前一節咱們簡單使用了int轉換器將同級的兩種傳遞參數的方式區分開來,否則查詢字符串方式會被第一種傳遞參數方式所捕獲。
咱們的轉換器是用在path函數中,因此有必要簡單介紹下path函數,這裏只簡單介紹第一個參數,下一篇文章會詳細講path函數的使用方法。
path函數簽名以下:
path(route,view,name=None,kwargs=None)
route 參數: url 的匹配規則。這個參數中能夠指定 url 中須要傳遞的參數,好比在訪問文章詳情頁的時候,能夠傳遞一個 id 。傳遞參數是經過 <> 尖括號來進行指定的。而且在傳遞參數的時候,能夠指定這個參數的數據類型,好比文章的 id 都是 int 類型,那麼能夠這樣寫 <int:id> ,之後匹配的時候,就只會匹配到 id 爲 int 類型的 url ,而不會匹配其餘的 url ,而且在視圖函數中獲取這個參數的時候,就已經被轉換成一個 int 類型了。
其中還有幾種經常使用的轉換器類型:
1.str:非空的字符串類型。默認的轉換器。可是不能包含斜槓。
2.int:匹配任意的零或者正數的×××。到視圖函數中就是一個int類型。
3.slug:由英文中的橫槓 - ,或者下劃線 _ 鏈接英文字符或者數字而成的字符串。
4.uuid:匹配 uuid 字符串。
5.path:匹配非空的英文字符串,能夠包含斜槓。
Tips:經過from django.urls import converters能夠導入定義轉換器的模塊。
下面重點介紹int、str、uuid轉換器,而slug和path轉換器再也不解釋。
str轉換器是默認的轉換器,表明若是在參數前面不添加任何東西,那麼將默認採用str轉換器。
在converters模塊中對str轉換器的定義以下圖:
其實說白了也就是一個類,而後定義了一個正則表達式,對傳遞的參數進行正則匹配。
在converters模塊中對int轉換器的定義以下圖:
從類的定義中能夠看出,它是匹配一個0-9的任意一個或多個以上的數字。
UUID 是 通用惟一識別碼(Universally Unique Identifier)的縮寫,每一個人均可以建立不與其它人衝突的UUID。在這樣的狀況下,就不需考慮數據庫建立時的名稱重複問題。目前最普遍應用的UUID,是微軟公司的全局惟一標識符(GUID)。全局惟一標識符(GUID,Globally Unique Identifier)是一種由算法生成的二進制長度爲128位的數字標識符。GUID的總數達到32^128個,因此隨機生成兩個相同GUID的可能性極小,但並不爲0。GUID的格式爲:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",其中每一個 x 是 0-9 或 a-f 範圍內的一個4位十六進制數,因此每一個x表明4個二進制位,因此4*32=128個二進制位,即GUID的總數達到32^128個。例如:6F9619FF-8B86-D011-B42D-00C04FC964FF 即爲有效的 GUID 值。
在converters模塊中對uuidt轉換器的定義以下圖:
在咱們的項目中,不可能只有一個 app ,若是把全部的 app 的 views 中的視圖都放在 first_project項目的urls.py 中進行映射,確定會讓代碼顯得很是亂。
就像咱們目前的項目同樣顯得十分混亂,多個book的視圖映射都放在一塊兒,以下圖:
所以 django 給咱們提供了一個方法,能夠在 app 內部包含本身的 url 匹配規則,而在項目的 urls.py 中再統一包含這個 app 的 urls 。使用這個技術須要藉助 include 函數,對include函數的使用下一篇會有詳細講解,這裏只要知道它的做用便可。
好,如今my_app包裏添加一個urls.py文件,代碼修改以下:
from django.urls import path from my_app import views from django.urls import converters urlpatterns = [ path('', views.book_list), path('<int:book_id>/', views.book_detail), # <book_id>就是參數 path('pub/', views.book_pub) ]
而後將first_project項目的urls.py代碼修改以下:
from django.contrib import admin from django.urls import path,include from my_app import views from django.urls import converters urlpatterns = [ path('admin/', admin.site.urls), path('book/', include("my_app.urls")) ]
從上面兩個文件代碼的修改咱們能夠這樣理解:如今first_project項目的urls.py文件,將’book/‘本來的映射交給了my_app包裏的urls.py文件進行內部映射。其實這兩個文件之間的映射關係就至關於字符串的拼接,例如:'book/'拼接my_app的urls.py文件的'pub/'組合成’book/pub/‘,而後再映射到book_pub視圖函數。
運行結果以下,徹底沒有問題,跟分離前如出一轍: