1. 程式人生 > >Django自定義url(path)轉換器

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:

  1. 在“文章分類”引數傳到檢視函式之前要把這些分類分開來儲存到列表中。
    比如引數是python+django,那麼傳到檢視函式的時候就要變成['python','django']

  2. 而在使用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轉換器按照以下五個步驟來走:
  1. 定義一個類,直接繼承自object就可以了(不繼承也可以,在python3中已經變的都可以了)。
  2. 在類中定義一個屬性regex,這個屬性是用來限制url轉換器規則的正則表示式。(必須為‘regex’這個命名,否則Django會找不到轉換器的規則)
  3. 實現to_python(self,value)方法,這個方法是將url中的值轉換一下,然後傳給檢視函式的。
  4. 實現to_url(self,value)方法,這個方法是在做url反轉的時候,將傳進來的引數轉換後拼接成一個正確的url。
  5. 將定義好的轉換器,使用django.urls.converters.register_converter方法註冊到django中。