目录

Django基础-路由

bookandmusic
bookandmusic 2019年05月25日  ·  阅读 4

在视图完成之后,想要让客户端的请求可以正常匹配到对应的视图函数,就需要给每个视图函数做对应的路由映射。

路由匹配顺序

总分路由

Django的主要路由信息定义在工程同名目录下的urls.py文件中,该文件是Django解析路由的入口。

每个子应用为了保持相对独立,可以在各个子应用中定义属于自己的urls.py来保存该应用的路由。然后用主路由文件包含各应用的子路由数据。

在任何时候,urlpatterns都可以"include"其他URLconf模块。这本质上是一组位于其他url之下的"roots"

每当Django遇到时include(),它都会截断直到该处匹配的URL的任何部分,并将剩余的字符串发送到包含的URLconf中以进行进一步处理。

  • djangodemo/urls.py:项目总路由
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('book.urls'))   # 包含图书应用的子路由	
]
  • apps/book/urls.py: 图书应用的子路由
from django.urls import path
from .views import Index

urlpatterns = [
    path('', Index.as_view()),
]

主路由

也可将工程的全部路由信息都定义在主路由文件中,子应用不再设置urls.py

from django.contrib import admin
from django.urls import path
from book.views import Index

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', Index.as_view())
]

路由匹配规则

path

  • path: 写的非正则路由(route

  • 两个必须参数:routeview;两个可选参数:kwargsname。即路由视图是必填参数

    • route 是一个匹配URL的准则(类似正则表达式)。当Django响应一个请求时,它会从urlpatterns的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。这些准则不会匹配GET和POST参数或域名。例如,URLconf在处理请求https://www.example.com/myapp/时,它会尝试匹配myapp/。处理请求https://www.example.com/myapp/?page=3 时,也只会尝试匹配 myapp/

    • view:当 Django 找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个HttpRequest对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入。

    • kwargs:任意个关键字参数可以作为一个字典传递给目标视图函数。

    • name: 为你的URL取名能使你在 Django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个URL模式

  • 正则捕获到的参数都是字符串,所以如果函数需要用的其他数据类型,可以在函数中直接转换,也可以在路由中直接转换。

  • 转换器(django2.0 以上默认使用的是path转换器)

    • str,匹配除了路径分隔符(/)之外的非空字符串
    • int,匹配正整数,包含0。
    • slug,匹配字母、数字以及横杠、下划线组成的字符串。
    • uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
    • path,匹配任何非空字符串,包含了路径分隔符(/)(不能用问号,因为问号在url地址有特殊含义。)
from django.urls import path
from . import views

urlpatterns = [
  path('articles/2003/', views.special_case_2003),
  path('articles/<int:year>/', views.year_archive),
  path('articles/<int:year>/<int:month>/', views.month_archive),
  path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
/articles/2005/03/  # 将匹配第三条,并调用views.month_archive(request, year=2005, month=3);
/articles/2003/  # 匹配第一条,并调用views.special_case_2003(request);
/articles/2003  # 将一条都匹配不上,因为它最后少了一个斜杠,而列表中的所有模式中都以斜杠结尾;
/articles/2003/03/building-a-django-site/  # 将匹配最后一个,并调用views.article_detail(request, year=2003, month=3, slug="building-a-django-site"

注意:

  • 要捕获一段url中的值,需要使用尖括号,而不是之前的圆括号;

  • 可以转换捕获到的值为指定类型,比如例子中的int。默认情况下,捕获到的结果保存为字符串类型,不包含/这个特殊字符;

  • 匹配模式的最开头不需要添加/,因为默认情况下,每个url都带一个最前面的/

re_path

如果路径和转换器语法不足以定义URL模式,则也可以使用正则表达式。使用 re_path()代替path()

Python正则表达式中,已命名正则表达式组的语法为(?P<name>pattern),其中name是组的名称,并且 pattern是要匹配的某种模式。

示例URLconf,使用正则表达式重写:

from django.urls import path, re_path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]

注意:

  • 无论正则表达式进行哪种匹配,每个捕获的参数都将作为字符串发送到视图。
  • 当从使用re_path()切换为使用path(), re_path()反之亦然时,特别重要的是要注意视图参数的类型可能会发生变化,因此您可能需要调整视图。
  • 当命名的组与未命名的组两种样式混合使用时,任何未命名分组path('(\d+)/',view)都会被忽略,只有命名分组path('(?P<year>\d+)/',view)才会传递到视图函数。
  • 未命名分组将正则表达式匹配到的内容当作位置参数,命名分组将正则表达式匹配到的内容当作关键字参数。
分类: Python
标签: django