Django路由
一、路由流程
1. 用户浏览器发出请求后,通过根url设置,去找urlpattern变量。在setting.py中对 ROOT_URLCONF进行配置,以确定根URLconf(URL configuration)路径。
2. 在urlpattern变量(一个django.conf.urls.url()实例的列表)中,从上往下寻找匹配其中正则表达式的url。一般是分解为两级路由。首先是在项目(project)目录下的urls.py中的urlpatterns。通过这里的主urls文件导航到应用(app)urls文件。
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^polls/', include('polls.urls')), url(r'^admin/', admin.site.urls), ]
include语法导向应用的路由,它会去掉URL 中匹配的部分并将剩下的字符串发送给include包含的URLconf做进一步处理。这里的正则表达式后面没有$,即以该字符串开头的即可匹配上。include的背后是一种即插即用的思想,即不关心具体app的路由策略,只管往指定的下一级路由转发,这样具体下一级urls文件可以放置在任何位置,不用拷贝到当前应用目录下。实际上,路由的层数可以不止两级,即include指向的urlpatterns还可以使用include指向下一级(参见本文2.7)。
3. 其次,在应用文件夹下新建urls.py,这里的urls文件负责处理具体的视图函数映射。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.index, name='index'), ]
4. 最后, 如果没有匹配到url,或抛出一个异常,将触发默认的错误处理视图函数。
可以在根URLconf中设定handler400,handler403,handler404,handler500进行自定义。
二、urlpatterns语法
示例代码如下:
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), ]
1. url()函数可以传递4个参数,其中2个是必须的:regex和view,以及2个可选的参数:kwargs和name。
regex是一个正则表达式。
view指定视图函数,或者用include()函数作为url分解器。include()函数中可以定义namespace,方便在视图模板中以{% url 'polls:index' %}方式反查url。
kwargs任意数量的关键字参数可以作为一个字典传递给视图函数,视图函数再传递给视图模板(函数形参的名字应该和字典key的名字一致)。
name对你的URL进行命名,可以让你能够在Django的任意处,尤其是模板内显式地引用它。相当于给URL取 了个全局变量名。
2. 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。没有命名的正则表达式组(通过圆括号)捕获的值以位置参数传递给视图函数。可以使用命名的正则表达式组来捕获URL中的值并以关键字参数传递给视图函数。
(注意:捕获的参数都是字符串,即使比如看上去像数字。如果是命名的正则表达式组,函数形参的名字应该和组的名字一致。也就是说可以从url中提取关键字参数,或者直接通过url函数中给定的字典,传递给视图函数,前者是一个可变值,取决于用户输入的url,后者是程序中设定的固定值)
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$')
def test(request, year, month):
PASS
3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
4. 每个正则表达式前面的'r' 是可选的但是建议加上。
在Python的string前面加上‘r’, 是为了告诉编译器这个string是个raw string,不要转意backslash '\' 。 例如,\n 在raw string中,是两个字符,\和n, 而不会转义为换行符。由于正则表达式和 \ 会有冲突,因此,当一个字符串使用了正则表达式后,最好在前面加上'r'。
5. URLconf进行匹配时将不包括GET或POST请求方式的参数以及域名。
http://www.example.com/myapp/ #URLconf 将查找myapp/。 http://www.example.com/myapp/?page=3 #URLconf 仍将查找myapp/。
6. 指定视图参数的默认值有一个方便的小技巧,是指定视图参数的默认值。
# 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"): ……
在上面的例子中,两个URL模式指向同一个视图views.page —— 但是第一个模式不会从URL 中捕获任何值。如果第一个模式匹配,page() 函数将使用num参数的默认值"1"。如果第二个模式匹配,page() 将使用正则表达式捕获的num 值。
7. include()的多级路由方法。如下,请求 /credit/reports/ 将调用credit_views.report()视图函数。
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)), ]
还可以如下使用,以减少重复部分。
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), ])), ]