美文网首页
4.Django路由系统

4.Django路由系统

作者: 免跪姓黄 | 来源:发表于2020-07-13 08:08 被阅读0次

    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/<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),
        ]
        
      • 注意:

        • 要从 URL 中取值,使用尖括号。
        • 捕获的值可以选择性地包含转换器类型。比如,使用 <int:name> 来捕获整型参数。如果不包含转换器,则会匹配除了 / 外的任何字符。
        • 路径的最前面不需要添加反斜杠,因为每个 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/<yyyy:year>/', views.year_archive),
            ...
        ]
        

    1. URLconf使用正则表达式

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

      在 Python 正则表达式中,命名正则表达式组的语法是 (?P<name>pattern) ,其中 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<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),
      ]
      

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

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

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


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

      • 还有命名组语法,例如 (?P<year>[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/<int:id>/', 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('<page_slug>-<page_id>/history/', views.history),
            path('<page_slug>-<page_id>/edit/', views.edit),
            path('<page_slug>-<page_id>/discuss/', views.discuss),
            path('<page_slug>-<page_id>/permissions/', views.permissions),
        ]
        
      • 我们可以改进它,通过只声明共同的路径前缀一次并将后面的部分分组:

        from django.urls import include, path
        from . import views
        
        urlpatterns = [
            path('<page_slug>-<page_id>/', 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/<int:year>/', views.year_archive, name='news-year-archive'),
            #...
        ]
        
      • 在模板里面可以这样引用:

        <a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
        {# Or with the year in a template context variable: #}
        <ul>
        {% for yearvar in year_list %}
        <li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
        {% endfor %}
        </ul>
        
      • 在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路由系统

          本文链接:https://www.haomeiwen.com/subject/mubocktx.html