Django框架之路由详解

对于优秀的Web应用来说,使用简洁,优雅的URL模式是一个非常值得重视的细节。

Django允许您自由地设计自己的URL,无需框架束缚。

为了给一个应用设计URL,您需要创建一个Python模块,通常被称为 URLconf (URL配置)。

这个模块是纯粹的Python代码,包含URL模式(简单的正则表达式)到Python函数(你的视图)的简单映射。

Django如何处理一个请求

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

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

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

  3. Django依次匹配每个URL模式,在与请求的URL匹配的第一个模式停下来。

  4. 一旦有URL匹配成功,Djagno引入并调用相关的视图,这个视图是一个简单的Python函数(或基于类的
    视图基于
    类的视图)。

    • 一个HttpRequest实例。
    • 如果匹配的URL返回没有命名组,那么来自正则表达式中的匹配项将作为位置参数提供。
    • 关键字参数由路径表达式匹配的任何命名部分组成,并由django.urls.path()django.urls.re_path()的可选kwargs参数中指定的任何参数覆盖。
  5. 如果没有URL被匹配,或者匹配过程中出现了异常,Django会调用一个适当的错误处理视图。参加下面的错误处理( 错误处理)。

Django框架中的路由定义方式

  • django.urls.path()
  • django.urls.re_path()

区别:

path(). 是定义字符串为url规则,

re_path() 可以是字符串或者字符串和正则的组合

  1. path('abc/',views.abcdef),
  2. re_path(r'^\w{3}/$',views.strdef),
  3. # ^ 在正则表达式中 代表 限制开始
  4. # \w 在正则表达式中 代表 单个的 字母/数字/下划线
  5. # {3} 在正则表达式中 代表匹配的次数
  6. # $ 在正则表达式中 代表 限制结尾
  7. # '^\w{3}/$' 就整体代表 字母/数字/下划线 三位组成的 字符串 以 /结尾
  8. # abb/a12/a_11/ 不符合 字符长度不对,开始和结尾不对。

Django框架中路由的参数捕获

1.使用path可以捕获url中的一部分内容作为视图函数的关键字参数进行传递

  1. # urls
  2. # 路由中可以使用<类型:参数名>的方式来捕获url中的一部分作为参数使用
  3. path('arts/<int:year>/', views.year_archive),
  4. path('arts/<int:year>/<int:month>/', views.month_archive),
  5. # 路由中如果定义了参数,那么对应的视图函数中也必须定义,并且要参数名一致
  6. def year_archive(request,year):
  7. '''
  8. 在路由当中指定来参数,那么对应的视图函数中则必须定义该参数
  9. '''
  10. return HttpResponse(f'year_archive:{year}')
  11. def month_archive(request,year,month):
  12. return HttpResponse(f"month_archive:{year},{month}")

2.re_path 捕获url中的内容作为参数

re_path() 中可以使用 (?P<参数名>参数规则) 来捕获URL中的参数

  1. # re_path 捕获url中的内容作为参数
  2. re_path(r'^name/(?P<name>\w{3,8})/$',views.getname),
  3. re_path(r'^(?P<name>\w{3,8})/p/(?P<pid>\d{8})/$',views.getnamepost),
  4. # 非命名参数捕获,这样定义那么对应的视图函数中只要有这个行参就可以
  5. re_path(r'^(\w{3,8})/p/(\d{8})/$',views.gnamep),

URL反向的解析

通过案例来讲解url反向解析。

假如有这样一个URL的规则是解析到 显示文章的视图的映射

  1. # 路由 urls.py
  2. path('get/post/<int:id>/',views.getpost)
  3. # 视图 views.py
  4. def getpost(request,id):
  5. # 通过文章id获取文章数据
  6. # 把文章内容解析到模版中
  7. return HttpResponse(f'{id}:的文章内容。。。')

那么在需要定义链接地址的地方如 html的a链接中可以直接硬编码的方式定义链接例如

  1. <!-- index.html -->
  2. <a href="/get/post/3/">Python3编码规范-硬编码</a>

这样就可以在页面中,通过a链接跳转到对应的文章视图函数中,查看文章的内容。

但是这样做有一个致命的缺陷,一旦url规则发生变化或url规则较多时,非常容易出错

强烈建议不要硬编码URL

假如 把url路由的规则改变了,那么对应的链接就会失效,你能想象你需要更改整个网站中的链接的痛苦场景。

因此,Django的路由可以设置 url反向解析来一劳永逸的解决这个问题。

1.在定义对应的路由规则时,只需要给定义的路由设置name关键字参数。路由名字。

  1. # 在定义路由时,可以指定路由的名字,在使用时通过路由名动态解析路由规则 url
  2. path('getpost/<int:id>/',views.getpost,name="home_getpost")

2.在需要使用url的html页面中可以使用 url标签进行动态的反向解析

  1. <!-- index.html -->
  2. <!-- {% url '路由名' 路由捕获参数 %} -->
  3. <a href="{% url 'home_getpost' 3 %}">Python3编码规范-反向解析</a>

3.不管你路由规则怎么变化,只要路由名称不变,那么通过反响解析的链接也不需要更改

url反向解析的使用

  • html模版中 可以使用 url 标签来反向解析
  • 在其他的python代码中 使用 reverse() 方法进行反向解析。django.url.reverse()