django路由

403 阅读3分钟

路由

这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战

1、Django 如何处理一个请求

当一个用户请求Django 站点的一个页面,下面是Django 系统决定执行哪个Python 代码使用的算法:

  1. Django 确定使用根 URLconf 模块。通常,这是 ROOT_URLCONF设置的值,但如果传入 HttpRequest 对象拥有 urlconf属性(通过中间件设置),它的值将被用来代替 ROOT_URLCONF 设置。

  2. Django 加载该 Python 模块并寻找可用的 urlpatterns 。它是 django.urls.path() 和(或) django.urls.re_path()

  3. Django 会按顺序遍历每个 URL 模式,然后会在所请求的URL匹配到第一个模式后停止,并与 path_info 匹配。

  4. 一旦有 URL 匹配成功,Djagno 导入并调用相关的视图,这个视图是一个Python 函数(或基于类的视图 class-based view。视图会获得如下参数:

    • 一个 HttpRequest 实例。

    • 如果匹配的 URL 包含未命名组,那么来自正则表达式中的匹配项将作为位置参数提供。

    • 关键字参数由路径表达式匹配的任何命名部分组成,并由 django.urls.path() 或 django.urls.re_path() 的可选 kwargs 参数中指定的任何参数覆盖。

  5. 如果没有 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] :09的数字和a到z的字符
. 匹配换行符之外的标志
+一个或多个
?0个或1个
*0个或多个
                

注意事项

  1. urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
  2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
  3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
  4. 每个正则表达式前面的'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")