0基礎掌握Django框架(6)視圖與URL分發器
URL分發器
為了更好的學習效果,請搭配視頻教程一起學習:
Django零基礎到項目實戰 - 網易雲課堂視圖:
視圖一般都寫在app
的views.py
中。並且視圖的第一個參數永遠都是request
(一個HttpRequest)對象。這個對象存儲了請求過來的所有信息,包括攜帶的參數以及一些頭部信息等。在視圖中,一般是完成邏輯相關的操作。比如這個請求是添加一篇博客,那麼可以通過request來接收到這些數據,然後存儲到資料庫中,最後再把執行的結果返回給瀏覽器。視圖函數的返回結果必須是HttpResponseBase
對象或者子類的對象。示例代碼如下:
from django.http import HttpResponse
def book_list(request):
return HttpResponse("書籍列表!")
URL映射:
視圖寫完後,要與URL進行映射,也即用戶在瀏覽器中輸入什麼url
的時候可以請求到這個視圖函數。在用戶輸入了某個url
,請求到我們的網站的時候,django
會從項目的urls.py
文件中尋找對應的視圖。在urls.py
文件中有一個urlpatterns
變數,以後django
就會從這個變數中讀取所有的匹配規則。匹配規則需要使用django.urls.path
函數進行包裹,這個函數會根據傳入的參數返回URLPattern
或者是URLResolver
的對象。示例代碼如下:
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)
]
URL中添加參數:
有時候,url
中包含了一些參數需要動態調整。比如簡書某篇文章的詳情頁的url,是https://www.jianshu.com/p/a5aab9c4978e
後面的a5aab9c4978e
就是這篇文章的id
,那麼簡書的文章詳情頁面的url就可以寫成https://www.jianshu.com/p/<id>
,其中id就是文章的id。那麼如何在django
中實現這種需求呢。這時候我們可以在path
函數中,使用尖括弧的形式來定義一個參數。比如我現在想要獲取一本書籍的詳細信息,那麼應該在url
中指定這個參數。示例代碼如下:
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)
]
而views.py
中的代碼如下:
def book_detail(request,book_id):
text = "您輸入的書籍的id是:%s" % book_id
return HttpResponse(text)
當然,也可以通過查詢字元串的方式傳遞一個參數過去。示例代碼如下:
urlpatterns = [
path(admin/, admin.site.urls),
path(book/,views.book_list),
path(book/detail/,views.book_detail)
]
在views.py
中的代碼如下:
def book_detail(request):
book_id = request.GET.get("id")
text = "您輸入的書籍id是:%s" % book_id
return HttpResponse(text)
以後在訪問的時候就是通過/book/detail/?id=1
即可將參數傳遞過去。
URL中包含另外一個urls模塊:
在我們的項目中,不可能只有一個app
,如果把所有的app
的views
中的視圖都放在urls.py
中進行映射,肯定會讓代碼顯得非常亂。因此django
給我們提供了一個方法,可以在app
內部包含自己的url
匹配規則,而在項目的urls.py
中再統一包含這個app
的urls
。使用這個技術需要藉助include
函數。示例代碼如下:
# first_project/urls.py文件:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path(admin/, admin.site.urls),
path(book/,include("book.urls"))
]
在urls.py
文件中把所有的和book
這個app
相關的url
都移動到app/urls.py
中了,然後在first_project/urls.py
中,通過include
函數包含book.urls
,以後在請求book
相關的url的時候都需要加一個book
的前綴。
# book/urls.py文件:
from django.urls import path
from . import views
urlpatterns = [
path(list/,views.book_list),
path(detail/<book_id>/,views.book_detail)
]
以後訪問書的列表的url
的時候,就通過/book/list/
來訪問,訪問書籍詳情頁面的url
的時候就通過book/detail/<id>
來訪問。
path函數:
path
函數的定義為:path(route,view,name=None,kwargs=None)
。以下對這幾個參數進行講解。
route
參數:url
的匹配規則。這個參數中可以指定url
中需要傳遞的參數,比如在訪問文章詳情頁的時候,可以傳遞一個id
。傳遞參數是通過<>
尖括弧來進行指定的。並且在傳遞參數的時候,可以指定這個參數的數據類型,比如文章的id
都是int
類型,那麼可以這樣寫<int:id>
,以後匹配的時候,就只會匹配到id
為int
類型的url
,而不會匹配其他的url
,並且在視圖函數中獲取這個參數的時候,就已經被轉換成一個int
類型了。其中還有幾種常用的類型:- str:非空的字元串類型。默認的轉換器。但是不能包含斜杠。
- int:匹配任意的零或者正數的整形。到視圖函數中就是一個int類型。
- slug:由英文中的橫杠
-
,或者下劃線_
連接英文字元或者數字而成的字元串。 - uuid:匹配
uuid
字元串。 - path:匹配非空的英文字元串,可以包含斜杠。
view
參數:可以為一個視圖函數或者是類視圖.as_view()
或者是django.urls.include()
函數的返回值。name
參數:這個參數是給這個url
取個名字的,這在項目比較大,url
比較多的時候用處很大。kwargs
參數:有時候想給視圖函數傳遞一些額外的參數,就可以通過kwargs
參數進行傳遞。這個參數接收一個字典。傳到視圖函數中的時候,會作為一個關鍵字參數傳過去。比如以下的url
規則:
from django.urls import path
from . import views
urlpatterns = [
path(blog/<int:year>/, views.year_archive, {foo: bar}),
]
那麼以後在訪問blog/1991/
這個url的時候,會將foo=bar
作為關鍵字參數傳給year_archive
函數。
re_path函數:
有時候我們在寫url匹配的時候,想要寫使用正則表達式來實現一些複雜的需求,那麼這時候我們可以使用re_path
來實現。re_path
的參數和path
參數一模一樣,只不過第一個參數也就是route
參數可以為一個正則表達式。
re_path
的示例代碼如下:from django.urls import path, re_path
from . import views
urlpatterns = [
path(articles/2003/, views.special_case_2003),
re_path(rarticles/(?P<year>[0-9]{4})/, views.year_archive),
re_path(rarticles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/, views.month_archive),
re_path(rarticles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[w-_]+)/, views.article_detail),
]
以上例子中我們可以看到,所有的route
字元串前面都加了一個r
,表示這個字元串是一個原生字元串。在寫正則表達式中是推薦使用原生字元串的,這樣可以避免在python
這一層面進行轉義。而且,使用正則表達式捕獲參數的時候,是用一個圓括弧進行包裹,然後這個參數的名字是通過尖括弧<year>
進行包裹,之後才是寫正則表達式的語法。
include函數:
在項目變大以後,經常不會把所有的url
匹配規則都放在項目的urls.py
文件中,而是每個app
都有自己的urls.py
文件,在這個文件中存儲的都是當前這個app
的所有url
匹配規則。然後再統一註冊到項目的urls.py
文件中。include
函數有多種用法,這裡講下兩種常用的用法。
include(pattern,namespace=None)
:直接把其他app
的urls
包含進來。示例代碼如下:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path(admin/, admin.site.urls),
path(book/,include("book.urls"))
]
當然也可以傳遞namespace
參數來指定一個實例命名空間,但是在使用實例命名空間之前,必須先指定一個應用命名空間。示例代碼如下:
# 主urls.py文件:
from django.urls import path,include
urlpatterns = [
path(movie/,include(movie.urls,namespace=movie))
]
然後在movie/urls.py
中指定應用命名空間。實例代碼如下:
from django.urls import path
from . import views
# 應用命名空間
app_name = movie
urlpatterns = [
path(,views.movie,name=index),
path(list/,views.movie_list,name=list),
]
include(pattern_list)
:可以包含一個列表或者一個元組,這個元組或者列表中又包含的是path
或者是re_path
函數。include((pattern,app_namespace),namespace=None)
:在包含某個app
的urls
的時候,可以指定命名空間,這樣做的目的是為了防止不同的app
下出現相同的url
,這時候就可以通過命名空間進行區分。示例代碼如下:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path(admin/, admin.site.urls),
path(book/,include(("book.urls",book)),namespace=book)
]
但是這樣做的前提是已經包含了應用命名空間。即在myapp.urls.py
中添加一個和urlpatterns
同級別的變數app_name
。
指定默認的參數:
使用path
或者是re_path
的後,在route
中都可以包含參數,而有時候想指定默認的參數,這時候可以通過以下方式來完成。示例代碼如下:
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/
的時候,因為沒有傳遞num
參數,所以會匹配到第一個url,這時候就執行view.page
這個視圖函數,而在page
函數中,又有num=1
這個默認參數。因此這時候就可以不用傳遞參數。而如果訪問blog/1
的時候,因為在傳遞參數的時候傳遞了num
,因此會匹配到第二個url
,這時候也會執行views.page
,然後把傳遞進來的參數傳給page
函數中的num
。
url反轉:
之前我們都是通過url來訪問視圖函數。有時候我們知道這個視圖函數,但是想反轉回他的url。這時候就可以通過reverse
來實現。示例代碼如下:
reverse("list")
> /book/list/
如果有應用命名空間或者有實例命名空間,那麼應該在反轉的時候加上命名空間。示例代碼如下:
reverse(book:list)
> /book/list/
如果這個url中需要傳遞參數,那麼可以通過kwargs
來傳遞參數。示例代碼如下:
reverse("book:detail",kwargs={"book_id":1})
> /book/detail/1
因為django
中的reverse
反轉url
的時候不區分GET
請求和POST
請求,因此不能在反轉的時候添加查詢字元串的參數。如果想要添加查詢字元串的參數,只能手動的添加。示例代碼如下:
login_url = reverse(login) + "?next=/"
自定義URL轉換器:
之前已經學到過一些django內置的url
轉換器,包括有int
、uuid
等。有時候這些內置的url轉換器
並不能滿足我們的需求,因此django給我們提供了一個介面可以讓我們自己定義自己的url轉換器。
自定義url
轉換器按照以下五個步驟來走就可以了:
regex
,這個屬性是用來保存url
轉換器規則的正則表達式。 3. 實現to_python(self,value)
方法,這個方法是將url
中的值轉換一下,然後傳給視圖函數的。 4. 實現to_url(self,value)
方法,這個方法是在做url
反轉的時候,將傳進來的參數轉換後拼接成一個正確的url。 5. 將定義好的轉換器,註冊到django中。比如寫一個匹配四個數字年份的url
轉換器。示例代碼如下:
# 1. 定義一個類
class FourDigitYearConverter:
# 2. 定義一個正則表達式
regex = [0-9]{4}
# 3. 定義to_python方法
def to_python(self, value):
return int(value)
# 4. 定義to_url方法
def to_url(self, value):
return %04d % value
# 5. 註冊到django中
from django.urls import register_converter
register_converter(converters.FourDigitYearConverter, yyyy)
urlpatterns = [
path(articles/2003/, views.special_case_2003),
# 使用註冊的轉換器
path(articles/<yyyy:year>/, views.year_archive),
...
]
為了更好的學習效果,請搭配視頻教程一起學習:
Django零基礎到項目實戰 - 網易雲課堂推薦閱讀:
TAG:Django(框架) |