談談Python之Django搭建企業級官網(第三篇上)

轉載請註明來源地址和原作者(CFishHome)

前沿

上一節的學前準備工作和第一個小牛試刀的Django項目學習,讓我們對Django開發越來越感興趣了。正所謂趁熱打鐵,讓我們繼續來學習網站開發必備的視圖函數和URL映射等知識,跟着步伐一起學習,我相信你會收穫很多。噔~噔,新聞播報時間:9月12-9月16有兩個超強颱風在廣東湛江登陸,沿途影響衆多城市,包括深圳!!所以很遺憾,前幾天打算和舍友去深圳遊玩的計劃泡湯了,也只能推遲幾天前往深圳度中秋、看月亮了~

DEBUG模式

無論是使用命令行還是Pycharm創建Django項目工程,settings.py文件的DEBUG都默認設置爲True,所以默認是開啓了DEBUG模式。如下圖所示:
談談Python之Django搭建企業級官網(第三篇上)
開啓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字段如下圖位置:
談談Python之Django搭建企業級官網(第三篇上)

URL分發器

我們在學習前先回顧下我們上一篇做了什麼。上一篇我們首先在Pycharm創建了一個名爲first_project的Django項目,然後在CMD使用命令創建了一個名爲my_app的app應用。注意,上篇因測試需要修改了IP地址和端口號,所以這裏我將項目的IP地址和端口號修改回127.0.0.1:8000,說明訪問這個IP就可以訪問我們的項目了。整體框架如下圖所示:
談談Python之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映射原理:用戶在瀏覽器輸入了某個 URL ,請求到我們的網站的時候, django 會從項目的 urls.py 文件中尋找對應的視圖。爲什麼會是在urls.py文件中尋找映射呢?這是因爲在"settings.py"文件中配置了"ROT_URLCONF"爲"urls.py"。在 urls.py 文件中有一個 urlpatterns 變量,以後 django 就會從這個變量中讀取所有的匹配規則。匹配規則需要使用 django.urls.path 函數進行包裹,這個函數會根據傳入的參數返回 URLPattern 或者是 URLResolver 的對象。

修改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,訪問成功!如下圖所示(圖片左下角顯示了"書籍列表!"文本內容):
談談Python之Django搭建企業級官網(第三篇上)
到了這裏朋友們可能會好奇如果輸入127.0.0.1:8000會怎麼樣?滿足你的好奇心,結果如下:
談談Python之Django搭建企業級官網(第三篇上)
我的天!我按照上一篇的流程可以訪問的啊,怎麼現在不彳亍了。其實當新添加了第一個URL映射之後需要注意的是主網頁127.0.0.1:8000的網頁404丟失了,這是因爲如果剛開始創建的項目,若還未添加過URL映射,那麼默認Django的底層提供一個就是那個火箭??頁面來映射,但若添加了,那麼就無法繼續映射那個火箭??頁面了,因爲看urlpatterns變量其實都沒有映射空URL,即127.0.0.1:8000爲空URL。

爲URL傳遞參數

爲URL傳遞參數有三種方式:

1.URL中添加參數

2.查詢字符串傳遞參數

3.指定默認的參數

URL中添加參數

有時候, url 中包含了一些參數需要動態調整。比如簡書某篇文章的詳情頁的url,是 https://www.jianshu.com/p/a5aab9c4978e 後面的 a5aab9c4978e 就是這篇文章的 id ,那麼簡書的文章詳情頁面的url就可以寫成 https://www.jianshu.com/p/<id&gt; ,其中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)

運行結果如下:
談談Python之Django搭建企業級官網(第三篇上)
對於多個參數也同樣類似,這裏不再測試。只不過在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 即可將參數傳遞過去。
運行結果如下:
談談Python之Django搭建企業級官網(第三篇上)
我們做個小測試,如果將轉換器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)
]

運行結果如下:
談談Python之Django搭建企業級官網(第三篇上)
通過上圖可以發現,跟我們預期的不太一樣,我們在瀏覽器輸入的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轉換器是默認的轉換器,代表如果在參數前面不添加任何東西,那麼將默認採用str轉換器。
在converters模塊中對str轉換器的定義如下圖:
談談Python之Django搭建企業級官網(第三篇上)
其實說白了也就是一個類,然後定義了一個正則表達式,對傳遞的參數進行正則匹配。

int轉換器

在converters模塊中對int轉換器的定義如下圖:
談談Python之Django搭建企業級官網(第三篇上)
從類的定義中可以看出,它是匹配一個0-9的任意一個或多個以上的數字。

uuid轉換器

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轉換器的定義如下圖:
談談Python之Django搭建企業級官網(第三篇上)

URL中包含另外一個urls模塊

在我們的項目中,不可能只有一個 app ,如果把所有的 app 的 views 中的視圖都放在 first_project項目的urls.py 中進行映射,肯定會讓代碼顯得非常亂。
就像我們目前的項目一樣顯得十分混亂,多個book的視圖映射都放在一起,如下圖:
談談Python之Django搭建企業級官網(第三篇上)
因此 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視圖函數。

運行結果如下,完全沒有問題,跟分離前一模一樣:
談談Python之Django搭建企業級官網(第三篇上)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章