4.Django路由系统

Django路由系统

  1. URL调度器

    • Django 允许自由地设计你的URL,不受框架束缚。Django认为,对于高质量的Web 应用来说,使用简洁、优雅的URL 模式是一个非常值得重视的细节。
    • 为了给一个应用设计URL,你需要创建一个Python 模块,通常被称为URLconf(URL configuration)。URLconf也被称作路由系统,这个模块是纯粹的Python 代码,包含URL 模式(简单的正则表达式)到Python 函数(你的视图)的简单映射。可以把URLconf比作书的目录。

  1. URLconf的基本格式

    • 在Django项目名称目录(以项目名称为:"Django" 为例)的urls.py文件中,找到urlpatterns

      from django.urls import path
      from app import views   # 从app中导入views
      
      urlpatterns = [
          path('articles/2003/', views.special_case_2003),
          path('articles//', views.year_archive),
          path('articles///', views.month_archive),
          path('articles////', views.article_detail),
      ]
      
    • 注意:

      • 要从 URL 中取值,使用尖括号。
      • 捕获的值可以选择性地包含转换器类型。比如,使用 来捕获整型参数。如果不包含转换器,则会匹配除了 / 外的任何字符。
      • 路径的最前面不需要添加反斜杠,因为每个 URL 都有。比如,应该是 articles 而不是 /articles 。

  1. URLconf的路径转换器

    下面的路径转换器在默认情况下是有效的:

    • str - 匹配除了 '/' 之外的非空字符串。如果表达式内不包含转换器,则会默认匹配字符串。
    • int - 匹配0或任何正整数。返回一个 int 。
    • slug - 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,building-your-1st-django-site
    • uuid - 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。
    • path - 匹配非空字段,包括路径分隔符 '/' 。它允许你匹配完整的 URL 路径而不是像 str 那样只匹配 URL 的一部分。

  1. URLconf注册自定义的路径转换器

    对于更复杂的匹配需求,可以定义自己的路径转换器。

    转换器是一个类,包含如下内容:

    • 字符串形式的 regex 类属性。

    • to_python(self, value) 方法,它处理匹配的字符串转换为应该传递到函数的类型。如果没有转换为给定的值,它应该会引发 ValueErrorValueError 被解释为不匹配,因此向用户发送404响应。

    • to_url(self, value) ,处理将 Python 类型转换为 URL 中要使用的字符串。

      class FourDigitYearConverter:
          regex = '[0-9]{4}'
      
          def to_python(self, value):
              return int(value)
      
          def to_url(self, value):
              return '%04d' % value
      
    • 在 URLconf 中使用 register_converter() 来注册自定义的转换器类:

      from django.urls import path, register_converter
      from app import converters, views
      
      register_converter(converters.FourDigitYearConverter, 'yyyy')
      
      urlpatterns = [
          path('articles/2003/', views.special_case_2003),
          path('articles//', views.year_archive),
          ...
      ]
      

  1. URLconf使用正则表达式

    如果路径和转化器语法不能很好的定义你的 URL 模式,你可以可以使用正则表达式。如果要这样做,请使用 re_path() 而不是 path()

    在 Python 正则表达式中,命名正则表达式组的语法是 (?Ppattern) ,其中 name 是组名,pattern 是要匹配的模式。

    这里是先前 URLconf 的一些例子,现在用正则表达式重写一下:

    from django.urls import path, re_path
    from app import views
    
    urlpatterns = [
        path('articles/2003/', views.special_case_2003),
        re_path(r'^articles/(?P[0-9]{4})/$', views.year_archive),
        re_path(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive),
        re_path(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[\w-]+)/$', views.article_detail),
    ]
    

    这实现了与前面示例大致相同的功能,除了:

    • 将要匹配的 URLs 将稍受限制。比如,10000 年将不在匹配,因为 year 被限制长度为4。
    • 无论正则表达式进行哪种匹配,每个捕获的参数都作为字符串发送到视图。

    当从使用 path() 切换到 re_path() (反之亦然),要特别注意,视图参数类型可能发生变化,你可能需要调整你的视图。


  1. URLconf使用未命名的正则表达式组

    • 还有命名组语法,例如 (?P[0-9]{4}) ,你也可以使用更短的未命名组,例如 ([0-9]{4})

    • 不是特别推荐这个用法,因为它会更容易在匹配的预期含义和视图参数之间引发错误。

    • 在任何情况下,推荐在给定的正则表达式里只使用一个样式。当混杂两种样式时,任何未命名的组都会被忽略,而且只有命名的组才会传递给视图函数。


  1. URLconf中包含其他的URLconfs

    • 在任何时候,你的 urlpatterns 都可以 "include" 其它URLconf 模块。这实际上将一部分URL 放置于其它URL 下面。例如,下面是URLconf Django website 自己的URLconf 中一个片段。它包含许多其它URLconf:

      from django.urls import include, path
      
      urlpatterns = [
          # ... snip ...
          path('community/', include('aggregator.urls')),
          path('contact/', include('contact.urls')),
          # ... snip ...
      ]
      
    • 每当 Django 遇到 include() ,它会将匹配到该点的URLconf的任何部分切掉,并将剩余的字符串发送到包含的URLconf进行进一步处理。另一种可能性是通过使用 path() 实例的列表来包含其他 URL 模式。比如,看这个 URLconf:

      from django.urls import include, path
      
      from apps.main import views as main_views
      from credit import views as credit_views
      
      extra_patterns = [
          path('reports/', credit_views.report),
          path('reports//', credit_views.report),
          path('charge/', credit_views.charge),
      ]
      
      urlpatterns = [
          path('', main_views.homepage),
          path('help/', include('apps.help.urls')),
          path('credit/', include(extra_patterns)),
      ]
      
    • 在这个例子中, /credit/reports/ URL将被 credit.views.report() 这个Django 视图处理。这种方法可以用来去除URLconf 中的冗余,其中某个模式前缀被重复使用。例如,考虑这个URLconf:

      from django.urls import path
      from . import views
      
      urlpatterns = [
          path('-/history/', views.history),
          path('-/edit/', views.edit),
          path('-/discuss/', views.discuss),
          path('-/permissions/', views.permissions),
      ]
      
    • 我们可以改进它,通过只声明共同的路径前缀一次并将后面的部分分组:

      from django.urls import include, path
      from . import views
      
      urlpatterns = [
          path('-/', include([
              path('history/', views.history),
              path('edit/', views.edit),
              path('discuss/', views.discuss),
              path('permissions/', views.permissions),
          ])),
      ]
      

  1. URL的命名和URL的反向解析

    • URLconf中支持给URL匹配规则和URL匹配模式起一个名字,这样我们以后就不需要写死URL代码了,只需要通过名字来调用当前的URL。例如,我们在urls.py中:

      from django.urls import path
      from app import views
      
      urlpatterns = [
          #...
          path('articles//', views.year_archive, name='news-year-archive'),
          #...
      ]
      
    • 在模板里面可以这样引用:

      2012 Archive
      {# Or with the year in a template context variable: #}
      
      
    • 在views函数中可以这样引用:

      from django.http import HttpResponseRedirect
      from django.urls import reverse
      
      def redirect_to_year(request):
          # ...
          year = 2006
          # ...
          return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
      

你可能感兴趣的:(4.Django路由系统)