路由
这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
1、Django 如何处理一个请求
当一个用户请求Django 站点的一个页面,下面是Django 系统决定执行哪个Python 代码使用的算法:
-
Django 确定使用根 URLconf 模块。通常,这是
ROOT_URLCONF设置的值,但如果传入HttpRequest对象拥有urlconf属性(通过中间件设置),它的值将被用来代替ROOT_URLCONF设置。 -
Django 加载该 Python 模块并寻找可用的
urlpatterns。它是django.urls.path()和(或)django.urls.re_path() -
Django 会按顺序遍历每个 URL 模式,然后会在所请求的URL匹配到第一个模式后停止,并与
path_info匹配。 -
一旦有 URL 匹配成功,Djagno 导入并调用相关的视图,这个视图是一个Python 函数(或基于类的视图 class-based view。视图会获得如下参数:
-
一个
HttpRequest实例。 -
如果匹配的 URL 包含未命名组,那么来自正则表达式中的匹配项将作为位置参数提供。
-
关键字参数由路径表达式匹配的任何命名部分组成,并由
django.urls.path()或django.urls.re_path()的可选kwargs参数中指定的任何参数覆盖。
-
-
如果没有 URL 被匹配,或者匹配过程中出现了异常,Django 会调用一个适当的错误处理视图。参加下面的错误处理Error handling
from django.conf.urls import url
urlpatterns = { #Django2.0了这里这是path,也可以在settings.py里面查看版本信息
url(正则表达式,views视图,参数,别名),
}
- 正则表达式:一个正则表达式字符串
- views视图:一个可调用对象,通常为一个视图函数
- 参数:可选的要传递给视图函数的默认参数(字典形式)
- 别名:一个可选的name参数
2、正则表达式
r'^articles/2003/'
r:原生字符串
^:以什么开头
$:以什么结尾
\d:数字 {}:几个数字范围 \w:字母 [0-9][a-z] :0到9的数字和a到z的字符
. 匹配换行符之外的标志
+一个或多个
?0个或1个
*0个或多个
注意事项
- urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
- 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
- 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的'r' 是可选的但是建议加上。
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/$', views.blog),
# blogs/2012/12/
url(r'^blogs/[0-9]{4}/\d{2}/$', views.blogs), #如果不写$的时候,我们访问blog/2002就会被blog给截胡了,因为是从上向下查找的
url(r'^blogs/[0-9]{4}/$', views.blogs), # blogs/2012/
]
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True #就是设置这个为False了django就不会默认加‘/’这个了
3、分组
url地址上捕获的参数会按照 位置传参 方式传递给视图函数
位置传参:()
url(r'^blogs/([0-9]{4})/(\d{2})/$', views.blogs),
url(r'^blogs/([0-9]{4})/$', views.blogs), # blogs/2012/
# 要在views.py里面接收参数
def blogs(request,x,y): #一个括号,表示一个参数(位置传参)
print(x,type(x))
print(y,type(y))
return HttpResponse("blogs")
4、命名分组
url地址上捕获的参数会按照 关键字传参 方式传递给视图函数
关键字传参:(?P<名称>) (?P<名称>)
url(r'^blogs/(?P<year>[0-9]{4})/(?P<month>\d{2})/$', views.blogs),
def blogs(request,year,month): # 这里的名称一定要和关键字对应
print(year,type(year))
print(month,type(month))
return HttpResponse("blogs")
def blogs(request,*args,**kwargs): #元组,和字典,这样也可以
print(args)
print(kwargs)
分组和命名分组,不能混合用。捕获的参数永远都是字符串
例1:
添加到项目中
1.url(r'^publishers_edit/(\d+)', views.publishers_edit), #表示获取1个或多个数字
2.设置views函数 def publishers_edit(request,id_pk): #通过位置传参,获得参数
3.设置html <a class="btn btn-primary btn-sm" href="/publishers_edit/{{ i.pk }}">编辑</a>
5、视图函数中指定默认值
# urls.py中
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$', views.page), #没有捕获取到东西的话,将会使用默认值 num=1
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
# views.py中,可以为num指定默认值
def page(request, num="1"):
pass
在上面的例子中,两个URL模式指向相同的view - views.page - 但是第一个模式并没有从URL中捕获任何东西。
如果第一个模式匹配上了,page()函数将使用其默认参数num=“1”,如果第二个模式匹配,page()将使用正则表达式捕获到的num值。
6、传递额外的参数给视图函数
url(r'^blogs/([0-9]{4})/$', views.blogs,{"k1":"v1"}), # blogs/2012/
def blogs(request,*args,**kwargs):
print(args) #('2012',)
print(kwargs) #{'k1': 'v1'}
return HttpResponse("blogs")