Django—路由(全面)

一個完整的路由包含:路由地址、視圖函數(或者視圖類)、可選變量和路由命名。

1、路由定義規則

路由稱爲URL,是對可以從互聯網上得到的資源位置和訪問方法的一種簡潔的表示,是互聯網標準資源的地址。互聯網上的每個文件都有一個唯一的路由,用於指出網絡文件的路徑位置。簡單說,路由可視爲我們常說的網址,每個網址代表不同的網頁。

1.1 Django2.X路由定義

這種路由設計模式下,工作原理如下:

  1. 運行MyDjango項目時,Django從MyDjango文件夾的urls.py找到各個App所定義的路由信息,生成完整的路由列表。
  2. 當用戶在瀏覽器上訪問某個路由地址時,Django就會收到該用戶的請求信息。
  3. Django從當前請求信息獲取路由地址,並在路由列表裏匹配相應的路由信息,再執行路由信息所指向的視圖函數(或視圖類),從而完成整個請求響應過程。

MyDjango文件夾的urls.py代碼如下:

from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    # 指向內置Admin後臺系統的路由文件sites.py
    path('admin/',admin.site.urls),
    # 指向index的路由文件urls.py
    path('',include('index.urls')),
]

MyDjango文件夾的urls.py定義兩條路由信息,分別是Admin站點管理和首頁地址(index)。其中,Admin站點管理在創建項目時已自動生成,一般情況下無需修改;首頁地址是指index文件夾的urls.py。MyDjango文件夾的urls.py的代碼解釋如下:

  • from django.contrib import admin:導入內置Admin功能模塊。
  • from django.urls import path,include:導入Django的路由函數模塊。
  • urlpatterns:代表整個項目的路由集合,以列表格式表示,每個元素代表一條路由信息。
  • path(‘admin/’,admin.site.urls):設定Admin的路由信息。'admin/'代表127.0.0.1:8000/admin的路由地址,admin後面的斜槓是路徑分隔符,其作用等同於計算機中文件目錄的斜杆符號;admin.site.urls指向內置Admin功能所自定義的路由信息,可以在Python目錄Lib\site-packages\django\contrib\admin\sites.py找到具體定義過程。
  • path(’’,include(‘index.urls’)):路由地址爲“\”,即127.0.0.1:8000,,通常是網站的首頁;路由函數include是將該路由信息分發給index的urls.py處理。這裏的index的urls.py來源在前面博客中講到了。

由於首頁地址分發給index的urls.py處理,因此下一步需要對index的urls.py編寫路由信息。如下:

# index的urls.py
from django.urls import path
from . import views
urlpatterns = [
	path('',views.index)
]

index的urls.py的編寫規則與MyDjango文件夾的urls.py大致相同,這是最爲簡單的定義方法,此外可參考內置Admin功能的路由定義方法。
在index的urls.py導入index的views.py文件,該文件用於編寫視圖函數或視圖類,主要用於處理當前請求信息並返回響應內容給用戶。路由信息path(’’,views.index)的views.index是指視圖函數index處理網站首頁的用戶請求和響應過程。因此,在index的views.py中編寫index函數的處理過程,代碼如下:

from django.shortcuts import render
def index(request):
    return render(request,'index.html')

index函數必須設置一個參數,參數命名不固定,但常以request進行命名,代表當前用戶的請求對象,該對象包含當前請求的用戶名、請求內容和請求方式等。
視圖函數執行完成後必須使用return將處理結果返回,否則程序會拋出異常信息。啓動MyDjango項目,在瀏覽器裏訪問即可。
路由文件urls.py的路由定義規則是相對固定的,路由列表由urlpatterns表示,每個列表元素代表一條路由。路由由Django的path函數定義的,該函數第一個參數是路由地址,第二個參數是路由所對應的處理函數(視圖函數或視圖類),這兩個參數是路由定義的必選參數。

1.2 路由變量的設置

在日常開發過程中,有時一個路由代表多個不同的頁面,如編寫帶有日期的路由,若根據前面的編寫方式,按一年計算,則需要開發者編寫365個不同的路由才能實現,實現這種做法明顯是不可取的。因此,Django在定義路由時,可以對路由設置變量值,使路由具有多樣性。
路由的變量類型有字符類型、整型、slug和uuid,最爲常用的使字符類型和整型。各個類型說明如下:

  • 字符類型: 匹配任何非空字符串,但不含斜杆,如果沒有指定類型,就默認使用該類型。
  • 整型: 匹配0和正整數。
  • slug: 可理解爲註釋、後綴或附屬等概念,常作爲路由的解釋性字符。可匹配ASCII字符以及連接符和下畫線,能使路由更加清晰易懂。比如網頁的標題是"14歲的小娃娃",其路由地址可以設置爲“14-sui-de-xiaowawa”。
  • uuid: 匹配一個uuid格式的對象。爲了防止衝突,規定必須使用“-”並且所有字母必須小寫,例如:075446e5-4646-fajkl46468

根據上述變量類型,在MyDjango項目的index文件夾的urls.py裏新定義路由,並且帶有字符類型、整型和slug的變量,代碼如下:

# index的urls.py文件
from django.urls.import.path
from . import views
urlpatterns = [
	# 添加帶有字符類型、整型和slug的路由
	path('<year>/<iny:month>/<slug:day>',views.myvariable)
]

在路由中,使用變量符號“<>”可以爲路由設置變量。在括號裏面以冒號劃分爲兩部分,冒號前面代表的是變量的數據類型,冒號後面代表的是變量名,變量名可自行命名,如果沒有設置變量的數據類型,就默認爲字符類型。上述代碼設置了3個變量,分別是<year>、<int:month>和<slug:day>,變量說明如下:

  • <year>:變量名爲year,數據格式爲字符類型,與<str:year>的含義一樣。
  • <int:month>:變量名爲month,數據格式爲整型。
  • <slug:day>:變量名爲day,數據格式爲slug。

在上述新增的路由中,路由的處理函數爲myvariable,因此在index的views.py中編寫myvariable的處理過程,代碼如下:

# views.py的myvariable函數
from django.http import HttpResponse
def myvariable(request,year,month,day):
	return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))

啓動項目,在瀏覽器上輸入127.0.0.1:8000/2020/04/19,運行結果則輸出2020/4/19。如果瀏覽器輸入的路由地址與其變量類型不相符合,Django就會提示Page not found。路由的變量和視圖函數的參數要一一對應,如果視圖函數的參數與路由的變量對不上,那麼程序會拋出不相符的報錯信息。
除了在路由地址設置變量外,Django還支持在路由地址外設置變量(路由的可選變量)。在index的urls.py和views.py中分別新增路由和視圖函數。代碼如下:

# index的urls.py
from django.urls import path
from . import views
urlpatterns = [
	# 添加帶有字符類型、整型和slug的路由
	path('<year>/<iny:month>/<slug:day>',views.myvariable),
	# 添加路由地址外的變量month
	path('',views.index,{'month':'2019/10/10'})
]

# index的views.py
from django.http import HttpResponse
def myvariable(request,year,month,day):
	return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))
	
def index(request,month):
	return HttpResponse('這是路由地址之外的變量:'+month)

從上述代碼可以看出,路由函數path的第3個參數是{‘month’:‘2019/10/10’},該參數的設置則如下:

  • 參數只能以字典的形式表示。
  • 設置的參數只能在視圖函數中讀取和使用。
  • 字典的一個鍵值對代表一個參數,鍵值對的鍵代表參數名,鍵值對的值代表參數值。
  • 參數值沒有數據格式限制,可以爲某個實例對象,字符串或列表(元組)等。

視圖函數index的參數必須對應字典的鍵,如果字典裏設置兩對鍵值對,視圖函數就要設置相應的函數參數,否則在瀏覽器上訪問的時候就會提示報錯信息。

1.3 正則表達式的路由定義

前面設置路由地址分別代表日期的年、月、日,其變量類型分別是字符類型、整型和sulg,因此在瀏覽器上輸入127.0.0.1/AAAA/05/01是合法的,但是不符合日期格式要求。爲了進一步規範日期格式,可以使用正則表達式限制路由地址變量的取值範圍。在index文件夾的urls.py裏使用正則表達式定義路由地址,代碼如下:

from django.urls import re_path
from . import views
urlpatterns = [
    re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2}/(?P<day>[0-9]{2})).html',views.mydate)
]

路由的正則表達式是由路由函數re_path定義的,其作用是對路由變量進行截取與判斷,正則表達式是以小括號爲單位的,每個小括號的前後可以使用斜杆或者其他字符將其分隔與結束。以上代碼爲例,分別將變量year、month和day以斜杆隔開,每個變量以一個小括號爲單位,在小括號內,可分爲3部分,以(?P<year>[0-9]{4})爲例。

  • ?P是固定格式,字母P必須爲大寫。
  • <year>爲變量名
  • [0-9]{4}是正則表達式的匹配模式,代表變量的長度爲4,只允許取0~9的值。

上述路由的處理函數mydate函數,因此還需要在index的views.py中編寫視圖函數mydate,代碼如下:

# views.py的mydate函數
from django.http import HttpResponse
def mydate(request,year,month,day):
    return HttpResponse(str(year)+'/'+str(month)+'/'+str(day))

路由地址末端設置了".html",這是一種僞靜態URL技術,可將網址設置爲靜態網址,用於SEO搜索引擎的爬取,如百度、谷歌等。此外,在末端設置".html"是爲變量day設置終止符,假如末端沒有設置".html",在瀏覽器上輸入無限長的字符串,路由也能正常訪問。

2、命令空間與路由命名

2.1 命名空間namespace

在MyDjango項目中創建新的項目應用user,並且在user文件裏創建urls.py,然後配置文件settings.py的INSTALLED_APPS中添加項目應用user,使得Django在運行的時候能夠識別項目應用user。在MyDjango文件夾的urls.py中重新定義路由信息,分別指向index文件夾的urls.py和user文件夾的urls.py,代碼如下:

from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    # 指向內置Admin後臺系統的路由文件sites.py
    path('admin/',admin.site.urls),
    # 指向index的路由文件urls.py
    path('',include(('index.urls','index'),namespace = 'index')),
    # 指向user的路由文件urls.py
    path('user/', include(('user.urls', 'user'), namespace='user')),
]

上述代碼中,新增的路由使用Django路由函數include並且指向index文件夾的urls.py和user文件夾的urls.py。在函數include裏設置了可選參數namespace,該參數是函數include特有的參數,這就是Django設置路由的命名空間。
路由函數include設有參數arg和namespace,參數arg指向項目應用App的urls.py文件,其數據格式以元組或字符串表示;可選參數namespace是路由的命名空間。
若要對路由設置參數namespace,則參數arg必須以元組格式表示,並且元組的長度必須爲2.元組的元素說明如下:

  • 第一個元素爲項目應用的urls.py文件,比如(“index.urls”,“index”)的"index.urls",這是代表項目應用index的urls.py文件。
  • 第二個元素可以自行命名,但不能爲空,一般情況下是以項目應用的名稱進行命名,(“index.urls”,“index”)的"index"是以項目應用index進行命名的。

如果路由設置參數namespace並且參數arg爲字符串或元組長度不足2的時候,在運行MyDjango的時候,Django就會提示錯誤信息。
接下來分析路由函數include的作用,它是將當前路由分配到某個項目應用的urls.py文件,而項目應用的urls.py文件可以設置多條路由,這種情況類似計算機上的文件夾A,並且該文件夾下包含多個子文件夾,而Django的命名空間namespace相當於對文件夾A進行命名。Django的命名空間namespace可以爲我們快速定位某個項目的urls.py,再結合路由命名name就能快速地從項目應用地urls.py找到某條路由地具體信息,這樣就能有效管理整個項目的路由列表。有關路由函數include的定義過程,可以在Python安裝目錄下找到源碼(Lib\site-packages\django\urls\conf.py)進行解讀。

2.2 路由命名name

上面都使用路由函數include並且分別指向index文件夾的urls.py和user文件夾的urls.py,命名空間namespace分別爲index和user。在此基礎上,我們在index文件夾的urls.py和user文件夾的urls.py中重新定義路由,代碼如下:

# index文件夾的urls.py
from django.urls import re_path,path
from . import views
urlpatterns = [
	re_path('(?P<year>[0-9]{4}.html)',views.mydate,name='mydate'),
	path('',views.index,name = 'index')
]

# user文件夾的urls.py
from django.urls import path
from . import views
urlpatterns =[
	path('index',views.index,name = 'index'),
	path('login',views.userLogin,name = 'userLogin')
]

每個項目應用的urls.py都定義了兩條路由,每條路由都由相應的視圖函數進行處理,因此在index文件夾的views.py和user文件夾的views.py中定義視圖函數,代碼如下:

# index文件夾的views.py
from django.http import HttpResponse
from django.shortcuts import render
def mydate(request,year):
	return HttpResponse(str(year))
def index(request):
	return render(request,'index.html')

# user文件夾的views.py
from django.http import HttpResponse
def index(request):
	return HttpResponse("This is userIndex")
def userLogin(request):
	return HttpResponse('This is userLogin')

項目應用index和user的urls.py所定義的路由都設置了參數name,這是對路由進行命名,它是路由函數path和re_path的可選參數。路由命名name的作用等同於文件夾裏的文件名。
如果路由裏使用路由函數include,就可以對該路由設置參數name,因爲路由的命名空間namespace是路由函數include的可選參數,而路由命名name是路由函數path或re_path的可選參數,兩者隸屬於不同的路由函數,因此可在同一路由裏共存一般情況下,使用路由函數include就沒必要再對路由設置參數name,儘管設置了參數name,但實際開發中沒有實質的作用。
注: 在不同項目應用的路由命名可以重複的,這種命名是合理的。但在一個項目中,多條路由是允許使用相同的命名的,這種方式是不合理的。
在實際開發中,支持使用路由命名,因爲網站更新或防止爬蟲程序往往需要頻繁修改路由地址,倘若在視圖或其他功能模塊裏使用路由地址,當路由地址發生更新變換時,這些模塊裏所使用的路由地址也要隨之修改,這樣就不利於版本的變更和維護;相對而言,如果在這些功能模塊裏使用路由命名來生成路由地址,就能避免路由地址的更新維護問題。

3、路由的使用方式

3.1 在模板中使用路由

從網站開發的角度分析,網站代表路由,若想將項目定義的路由的路由顯示在網頁上,則要在模板上使用模板語法來生成路由地址。Django內置了一套模板語法,它能將Python的語法轉換成HTML語言,然後通過瀏覽器解析HTML語言並生成相應的網頁內容。
項目環境搭建後,在MyDjango文件夾的urls.py中使用urls.py中使用路由函數path和include定義項目應用文件夾index的路由,代碼如下:

from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    # 指向內置Admin後臺系統的路由文件sites.py
    path('admin/',admin.site.urls),
    # 指向index的路由文件urls.py
    path('',include('index.urls'))
]

在項目應用的index裏,分別在urls.py和view.py文件中定義路由和視圖函數,並且在模板文件夾templates的index.html文件中編寫模板內容,代碼如下:

# index的urls.py
from django.urls import re_path,path
from . import views
urlpatterns = [
    # 添加帶有字符類型、整型和slug的路由
    re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2}/(?P<day>[0-9]{2})).html',views.mydate,name = 'mydate'),
    # 定義首頁的路由
    path('',views.index)
]

# templates的index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
</head>
<body>
    <span>Hello World!</span>
    <br>
    <a href="{% url 'mydate' '2020' '04' '10' %}">查看日期</a>
</body>
</html>

現分析index.html的模板內容,模板使用了Django內置的模塊語法url來生成路由地址,模板語法url設有4個不同的參數,其說明如下:

  • mydate: 代表命名mydate的路由。.
  • 2020: 代表路由地址變量year。
  • 04: 代表路由地址變量month。
  • 10: 代表路由地址變量day。
    注: 變量之間使用空格隔開。

模板語法的參數設置與路由定義是相互關聯的,具體說明如下:

  • 若路由地址存在變量,則模板語法url需要設置相應的參數值,參數值之間使用空間隔開。
  • 若路由地址不存在變量,則模板語法url只需設置路由命名name即可,無需設置額外參數。
  • 若路由地址的變量與模板語法url的參數數量不相同,則在瀏覽器訪問網頁的時候會提示NoReverseMatch at的錯誤信息。

上述例子中,MyDjango文件夾的urls.py在使用函數include定義路由時並沒有設置命名空間namespace。若設置了命名空間namespace,則模板裏使用路由的方式有所變化。下面對MyDjango文件夾urls.py和模板文件夾templates的index.html代碼進行修改:

# MyDjango文件夾的urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    # 指向內置Admin後臺系統的路由文件sites.py
    path('admin/',admin.site.urls),
    # 指向index的路由文件urls.py
    # path('',include('index.urls'))
    # 使用命名空間namespace
    path('',include(('index.urls','index'),namespace='index')),
]

# templates的index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
</head>
<body>
    <span>Hello World!</span>
    <br>
    {# <a href="{% url 'mydate' '2020' '04' '10' %}">查看日期</a>#}
    <a href="{% url 'index:mydate' '2020' '04' '10' %}">查看日期</a>
    
</body>
</html>

從模板文件index.html可以看出,若項目應用設有命名空間namespace,則模板語法url在使用路由,需要在命名路由name前面添加命名空間namespace並且使用冒號隔開,如:”namespace:name“。若路由在定義過程中使用命名空間namespace,而模板語法url沒有添加命名空間namespace,則在訪問網頁時,Django會提示報錯信息。

3.2 反向解析reverse與resolve

路由除了在模板裏使用之外,還可以在視圖裏使用。我們知道Django的請求生命週期是指用戶在瀏覽器訪問網頁時,Django根據網址在路由列表裏查詢相應的路由,再從路由裏找到視圖函數或視圖類進行處理,將處理結果作爲響應內容返回瀏覽器並生成網頁內容。這個生命週期是不可逆的,而在視圖裏使用路由這一過程被稱爲反向解析。 Django的反向解析主要由函數reverse和resolve實現,函數reverse是通過路由命名或視圖對象來生成路由地址的;函數resolve是通過路由地址來獲取路由對象信息的。
在MyDjango文件夾的urls.py和index文件夾的urls.py裏定義路由地址。代碼如下:

# MyDjango文件夾的urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    # 指向內置Admin後臺系統的路由文件sites.py
    path('admin/',admin.site.urls),
    # 指向index的路由文件urls.py
    path('',include('index.urls','index'),namespace ='index'),
]

# index文件夾的urls.py
from django.urls import path
from . import views
urlpatterns = [
	re_path('<year>/<int:month>/<slug:day>',view.mydate,name='mydate'),
	# 定義路由的首頁
	path('',views.index,name = 'index')
]

由於反向解析函數reverse和resolve常用於視圖(views.py)、模型(models.py)或Admin後臺(admin.py)等,因此在視圖(views.py)的函數mydate和index裏分別使用reverse和resolve,代碼如下:

from django.http import HttpResponse
from django.shortcuts import reverse
from django.urls import resolve

def mydate(request, year, month, day):
    args = ['2019', '12', '12']
    result = resolve(reverse('index:mydate', args=args))
    print('kwargs:', result.kwargs)
    print('url_name:', result.url_name)
    print('namespace:', result.namespace)
    print('view_name:', result.view_name)
    print('app_name:', result.app_name)
    return HttpResponse(str(year) + '/' + str(month) + '/' + str(day))

def index(request):
    kwargs = {'year': 2010, 'month': 2, 'day': 10}
    args = ['2019', '12', '12']
    print(reverse('index:mydate', args=args))
    print(reverse('index:mydate', kwargs=kwargs))
    return HttpResponse(reverse('index:mydate', args=args))

函數index主要使用反向解析函數reverse來生成路由mydate的路由地址。爲了進一步瞭解reverse,我們可以查看reverse的源碼文件。
函數reverse設有必選參數viewname,其餘參數是可選參數,各個參數說明如下:

  • viewname: 代表路由命名或可調用視圖對象,一般情況下是以路由命名name來生成路由地址的
  • urlconf: 設置反向解析的URLconf模塊。默認情況下,使用配置文件settings.py的ROOT_URLCONF屬性(MyDjango文件夾的urls.py)
  • args: 以列表方式傳遞路由地址變量,列表元素順序和數量應與路由地址變量的順序和數量一致。
  • kwargs: 以字典方式傳遞路由地址變量,字典的鍵必須對應路由地址變量名,字典的鍵值對數量與變量的數量一致。
  • current_app: 提示當前正在執行的視圖所在的項目應用,主要起到提示作用,在功能上並無實質的作用。

一般情況下只需設置函數reverse的參數viewname即可,如果路由地址設置變量,那麼可自行選擇參數args或kwargs設置路由地址的變量值。
接下來分析視圖函數mydate,它是在函數reverse的基礎上使用函數resolve。我們可以查看函數resolve源碼,可以看到,resolve設有兩個參數,參數path是必選參數,urlconf是可選參數。

  • path: 代表路由地址,通過路由地址來獲取對應的路由對象信息。
  • urlconf: 設置反向解析的URLconf模塊。默認情況下,使用配置文件settings.py的ROOT_URLCONF屬性(MyDjango文件夾的urls.py)。函數resolve是以對象作爲返回值的,該對象內置多種函數方法獲取具體的路由信息。具體函數可網上搜索。

綜上所說,函數reverse和resolve主要是對路由進行反向解析,通過路由命名和路由地址來獲取路由信息。在使用這兩個函數的時候,需要注意兩者所傳入的參數類型和返回值的數據類型。

3.3 路由重定向

重定向稱爲HTTP協議重定向,也可以稱爲網頁跳轉,它對HTTP狀態碼爲301、302、303、307、308。簡單來說,網頁重定向就是在瀏覽器訪問某個網頁的時候,這個網頁不提供響應內容,而是自動跳轉到其他網址,由其他網址來生成響應內容。
Django的網頁重定向有兩種方式:第一種方式是路由重定向;第二種方式是自定義視圖的重定向。 兩種重定向方式各有優點,前者是使用Django內置的視圖類RedirectView實現的,默認支持HTTP的GET請求;後者是在自定義視圖的響應狀態設置重定向,能讓開發者實現多方面開發需求。
我們在MyDjango項目裏分別講述Django的兩種重定向方式,在index的urls.py中定義trunTo,其代碼如下所示:

from django.urls import path
from . import views
from django.views.generic import RedirectView

urlpatterns = [
    # 添加帶有字符類型、整型和slug的路由
    path('<year>/<int:month>/<slug:day>', views.mydate, name='mydate'),
    # 定義首頁的路由
    path('', views.index, name='index'),
    # 設置路由跳轉
    path('trunTo', RedirectView.as_view(url='/'), name='trunTo'),
    # path('trunTo', RedirectView.as_view(pattern_name='index:index'), name='trunTo'),
]

在路由裏使用視圖類RedirectView必須使用as_view方法將視圖類實例化,參數url用於設置網頁跳轉的路由地址,"/"代表網站首頁(路由命名爲index的路由地址)。然後在index的views.py中定義視圖函數mydate和index,代碼如下:

from django.http import HttpResponse
from django.shortcuts import redirect
from django.shortcuts import reverse

def mydate(request, year, month, day):
    return HttpResponse(str(year) + '/' + str(month) + '/' + str(day))

def index(request):
    print(reverse('index:trunTo'))
    return redirect(reverse('index:mydate', args=[2019,12,12]))

視圖函數index使用重定向函數redirect實現網頁重定向的,這是Django內置的重定向函數,其函數參數只需傳入路由地址即可實現重定向。
運行MyDjango項目,在瀏覽器上輸入127.0.0.1:8000/turnTo,發現該網址首先通過視圖類RedirectView重定向首頁(路由命名爲index),然後在視圖函數index裏使用重定向函數redirect跳轉到路由命名爲mydate的路由地址,如圖所示:
在這裏插入圖片描述
從圖中看出,瀏覽器的開發者工具記錄了3條西悉尼,其中trunTo的請求信息是我們在瀏覽器輸入的網址,而名爲127.0.0.1的請求信息是網站首頁,兩者的HTTP狀態碼都是302,說明視圖類RedirectView和重定向函數redirect皆能實現網站的重定向。

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