Django自定義url(path)轉換器
需求1:
實現一個獲取電影列表的demo,使用者可以根據/movie/電影分類/
的方式來獲取電影。其中電影分類採用的是分類1+分類2+分類3...
的方式拼接的,並且如果只有一個分類,那就不需要加號。示例如下:
# 1. 第一種:獲取action分類下的電影
/movie/action/
# 2. 第二種:獲取action和costume分類下的電影
/movie/action+costume/
# 3. 第三種:獲取action和costume和love下的電影
/movie/action+costume+love/
以此類推...
首先在專案中新建一個movie的app,
在views.py中寫入程式碼:
from django.shortcuts import render,reverse
from django.http import HttpResponse
# Create your views here.
def movie(request):
return HttpResponse('電影首頁')
def movie_list(request,categories):
text = '你所選的分類是:%s' % categories
return HttpResponse(text)
def movie_detail(request,movie_id) :
reverse('detail',kwargs={'movie_id':movie_id})
print(type(movie_id))
return HttpResponse('電影詳情')
新建一個urls.py的檔案,編寫程式碼:
from django.urls import re_path,path
from . import views
urlpatterns = [
path('',views.movie),
re_path(r'list/(?P<categories>\w+|(\w+\+\w+)+)/',views. movie_list),
]
注意:正則表示式中不能隨便亂加空格
#\w 0-9,a-z,A-Z,_ 中的任意字元
#\w+ 一個或多個 “\w” 這樣的字元
# | 或者
#(\w+\+\w+)+: 一個或多個 “(\w+\+\w+)” 這樣的字元
# \w+ 一個或多個 “\w” 這樣的字元
# \+ "+"號
# \w+ 一個或多個 “\w” 這樣的字元
主urls.py中編寫程式碼:
from django.urls import path,include
urlpatterns = [
path('movie/',include('movie.urls')),
]
然後我們輸入網址進行測試
http://127.0.0.1:8000/movie/list/action
http://127.0.0.1:8000/movie/list/action+costume+love
現在我們就實現好了需求1.
需求2:
-
在“文章分類”引數傳到檢視函式之前要把這些分類分開來儲存到列表中。
比如引數是python+django
,那麼傳到檢視函式的時候就要變成['python','django']
。 -
而在使用reverse反轉的時候,限制傳遞“文章分類”的引數應該是一個列表如
['python','django']
,並且要將這個列表變成python+django
的形式。
在movie中的urls.py中匯入:
from django.urls import converters
然後按住ctrl鍵再單擊converters,就能進入到Django中內建的converters.py檔案中,我們可以模仿Django中內建的轉換器來自定義我們自己的轉換器。(Django內建的轉換器)
就以int這個轉換器的為例,int轉換器的結構為
class IntConverter:
regex = '[0-9]+'
def to_python(self, value):
return int(value)
def to_url(self, value):
return str(value)
為了規範程式碼結構,我們在movie這個app中建立一個converters.py檔案,在裡面編寫程式碼:
class CatagoryConverter(object):
#變數名必須為'regex',否則會找不到定義的字元竄規則
regex = r'\w+|(\w+\+\w+)+'
def to_python(self,value):
#python+Django+flask
# 到
#['python','Django','flask']
result = value.split("+")
return result
def to_url(self,value):
# ['python','Django','flask']
# 到
# python+Django+flask
#if判斷是為了增強程式碼的健壯性,如果傳遞過來的引數不是一個列表,就丟擲異常
if isinstance(value,list):
result = "+".join(value)
return result
else:
raise RuntimeError('轉換url的時候,分類引數必須為列表!')
#在定義好了轉換器之後還需要註冊,否則將不能生效。
register_converter(CatagoryConverter,'cate') #註冊自定義的轉換器
這樣我們就完全定義好了一個轉換器,我們給它取的名字為’cate’。
但是,我們將這個檔案放在converters.py這個檔案中,而我們沒有在任何一個地方執行了這個檔案。
所以我們需要執行這個檔案才能使用我們自定義的轉換器。
在movie目錄下有一個’__init__.py’的檔案,當movie這個模組被匯入時,會首先執行’__init__.py‘這個檔案中的內容,所以我們在’__init__.py‘匯入converters.py檔案,’__init__.py’中編寫程式碼:(. 表示當前目錄)
from . import converter
這樣我們就完全自定義好了一個‘cate’這樣的轉換器。
然後,跳轉至movie中的urls.py中修改程式碼為:
from django.urls import re_path,path
from . import views
from django.urls import converters
urlpatterns = [
path('',views.movie),
#re_path(r'list/(?P<categories>\w+|(\w+\+\w+)+)/',views.movie_list),
path('list/<cate:categories>/',views.movie_list,name = 'list'),
]
views.py檔案中修改程式碼:
from django.shortcuts import render,reverse
from django.http import HttpResponse
# Create your views here.
def movie(request):
return HttpResponse('電影首頁')
def movie_list(request,categories):
#這兩句print是為了檢視轉換的效果
print('轉換前:%s' % categories)
print(reverse('list',kwargs={'categories':categories}))
text = '你所選的分類是:%s' % categories
return HttpResponse(text)
然後我們儲存後執行程式碼,在瀏覽器中輸入:
http://127.0.0.1:8000/movie/list/action+love/
然後我們可以去控制檯中檢視列印的資訊,
如果在命名行中執行的專案那麼就在命令視窗中檢視資訊。
總結
之前已經學到過一些django內建的url轉換器,包括有int、uuid等。有時候這些內建的url轉換器並不能滿足我們的需求,因此django給我們提供了一個介面可以讓我們自己定義自己的url轉換器。
自定義url轉換器按照以下五個步驟來走:
- 定義一個類,直接繼承自object就可以了(不繼承也可以,在python3中已經變的都可以了)。
- 在類中定義一個屬性regex,這個屬性是用來限制url轉換器規則的正則表示式。(必須為‘regex’這個命名,否則Django會找不到轉換器的規則)
- 實現to_python(self,value)方法,這個方法是將url中的值轉換一下,然後傳給檢視函式的。
- 實現to_url(self,value)方法,這個方法是在做url反轉的時候,將傳進來的引數轉換後拼接成一個正確的url。
- 將定義好的轉換器,使用
django.urls.converters.register_converter
方法註冊到django中。