Django框架全面講解 -- Django 路由系統
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL模式以及要為該URL模式呼叫的檢視函式之間的對映表;你就是以這種方式告訴Django,對於這個URL呼叫這段程式碼,對於那個URL呼叫那段程式碼。URL的載入是從配置檔案中開始。
引數說明:
一個正則表示式字串
一個可呼叫物件,通常為一個檢視函式或一個指定檢視函式路徑的字串
可選的要傳遞給檢視函式的預設引數(字典形式)
一個可選的name引數
1. 示例
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$' , views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
說明:
要捕獲從URL中的值,用括號括起來,會當引數傳入 views 檢視。
沒有必要新增一個斜線,因為每個URL都有。例如,它^articles不是^/articles。
在’r’前面的每個正則表示式字串中是可選的,但建議。它告訴Python字串是“原始” -沒有什麼字串中應該進行轉義。
請求示例:
一個請求 /articles/2005/03/ 會匹配上面列表中的第三條. Django 會呼叫函式 views.month_archive(request, ‘2005’, ‘03’).
/articles/2005/3/ 不會匹配上面列表中的任何條目, 因為第三條的月份需要二位數字.
/articles/2003/ 會匹配上第一條而不是第二條,因為匹配是按照從上到下順序而進行的, Django 會呼叫函式 views.special_case_2003(request)
/articles/2003 不會匹配上面列表中的任何條目, 因為每個URL應該以 / 結尾.
/articles/2003/03/03/ 會匹配上最後一條. Django 會呼叫函式 views.article_detail(request, ‘2003’, ‘03’, ‘03’).
2. 命名組(Named groups)
在上面的簡單例子中,並沒有使用正則表示式分組,在更高階的用法中,很有可能使用正則分組來匹配URL並且將分組值通過引數傳遞給view函式。
在Python的正則表示式中,分組的語法是 (?Ppattern), name表示分組名,pattern表示一些匹配正則.
這裡是一個簡單的小例子:
# 正則知識
import re
ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo')
print(ret.group())
print(ret.group('id'))
print(ret.group('name'))
-------------------------------------
123/ooo
123
ooo
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$' , views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
For example:
A request to /articles/2005/03/ 會呼叫函式 views.month_archive(request, year='2005',month='03'), 而不是 views.month_archive(request, '2005', '03').
A request to /articles/2003/03/03/ 會呼叫函式 views.article_detail(request, year='2003',month='03', day='03').
常見寫法例項:
3. 二級路由(Including)
那如果對映 url 太多怎麼辦,全寫一個在 urlpatterns 顯得繁瑣,so 二級路由應用而生
from django.conf.urls import include, url
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
url(r'^reports/$', credit_views.report),
url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
url(r'^charge/$', credit_views.charge),
]
urlpatterns = [
url(r'^$', main_views.homepage),
url(r'^help/', include('apps.help.urls')),
url(r'^credit/', include(extra_patterns)),
]
在上面這個例子中,如果請求url為 /credit/reports/ 則會呼叫函式 credit_views.report().
使用二級路由也可以減少程式碼冗餘,使程式碼更加簡潔易懂。
# 原始版本
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]
# 改進版本
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
url(r'^history/$', views.history),
url(r'^edit/$', views.edit),
url(r'^discuss/$', views.discuss),
url(r'^permissions/$', views.permissions),
])),
]
4.新增額外的引數
URLconfs 有一個鉤子可以讓你加入一些額外的引數到view函式中.
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
在上面的例子中,如果一個請求為 /blog/2005/, Django 將會呼叫函式l views.year_archive(request, year=’2017’,foo=’bar’).
需要注意的是,當你加上引數時,對應函式views.year_archive必須加上一個引數,引數名也必須命名為 foo,如下:
def year_archive(request, foo):
print(foo)
return render(request, 'index.html')
5.別名的使用
url(r'^index',views.index,name='bieming')
url中還支援name引數的配置,如果配置了name屬性,在模板的檔案中就可以使用name值來代替相應的url值.我們來看一個例子:
urlpatterns = [
url(r'^index',views.index,name='bieming'),
url(r'^admin/', admin.site.urls),
# url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
# url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
# url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
###################
def index(req):
if req.method=='POST':
username=req.POST.get('username')
password=req.POST.get('password')
if username=='alex' and password=='123':
return HttpResponse("登陸成功")
return render(req,'index.html')
#####################
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{# <form action="/index/" method="post">#}
{# 這裡只要使用bieming即可代替/index #}
<form action="{% url 'bieming' %}" method="post">
使用者名稱:<input type="text" name="username">
密碼:<input type="password" name="password">
<input type="submit" value="submit">
</form>
</body>
</html>
#######################
6.指定view的預設配置
# URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
# View (in blog/views.py)
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.
...
在上述的例子中,兩個 URL 模式指向同一個檢視 views.page 但第一圖案不捕獲從 URL 任何東西。如果第一個模式匹配,該 page() 函式將使用它的預設引數 num,”1”。如果第二圖案相匹配時, page()將使用任何 num 值由正則表示式捕獲。