Django URLconf

Django URLconf,简洁优雅的URL结构是高质量Web应用程序的象征。Django允许开发人员设计任何形式的URL,这在早期的网站中是不可想象的。早期的网站通常会有很长的一串URL,而且通常URL还会包括一些无用信息,如.aspx.php等。

为了给应用程序设计URL,开发人员需要开发一个Python模块,这个模块就是URL的配置信息,通常我们将这个配置模块叫作URLconf。这个模块是一个纯粹的Python脚本,它包含了URL表达式与Python方法之间的映射,这里的Python方法就是Django应用中的视图方法。前面示例中的mysite/urls.pypolls/urls.py就是两个URLconf实例。

URLconf示例

下面是一个URLconf的简单示例:
Django URLconf

示例解读:

  • 函数path的第一个参数是一个URL模式字符串,用于匹配URL。
  • 函数path的第二个参数是用于处理URL请求的视图函数。
  • 使用尖括号提取URL中的参数,如<int:year>
  • 可使用类型转化器对参数类型进行转换,如int:会将从URL中捕获的值转换为数值类型,如果没有指定类型转换器,如<year>,则任何不包含/的字符串都会被提取。
  • URL模式字符串不需要以/开头。

应用场景:

  • 发送向/articles/2005/03/的请求将会与第三个URL模式字符串匹配成功,匹配成功后Django调用views.month_archive(request, year=2005, month=3)
  • 发送向/articles/2003/的请求将会与第一个URL模式字符串匹配成功而不是第二个,因为Django在第一个URL匹配成功后停止后续URL检验,匹配成功后Django调用views.special_case_2003(request)
  • 发送向/articles/2003的请求不会与任何URL模式字符串匹配成功,因为每个URL模式字符串都要求以/结束。
  • 发送向/articles/2003/03/building-a-django-site/的请求将会与最后一个URL模式字符串匹配成功,匹配成功后Django调用views.article_detail(request, year=2003, month=3, slug="building-a-django-site")

URL参数类型转化器

前面提到可以使用int对捕捉到的URL参数进行类型转换,下面是Django支持的所有类型转换器。

  • str:匹配任意非空字符串,但是不能匹配URL分隔符“/”。这是默认的URL参数转换器。
  • int:匹配任意大于等于0的整数。
  • slug:匹配任意slug字符串,slug字符串可以包含任意ASCII字符、数字、连字符“-”和下画线“_”
  • uuid:匹配UUID字符串(字符串中的字母必须为小写字母),例如:075194d3-6885-417e-a8a8-6c931e272f00
  • path:匹配任意非空字符串,包括URL分隔符“/”。这允许匹配完成的URL而不是URL的一个片段。

自定义URL参数类型转化器

对于更加复杂的URL场景,开发人员可以开发自定义参数类型转换器,自定义参数类型转换器包括以下几部分:

  • 一个regex属性,属性值为正则表达式。
  • 一个to_python(self, value)方法,该方法用于将匹配的URL参数转换为指定类型,当类型转换失败后抛出ValueError异常。
  • 一个to_url(self, value)方法,该方法用于将Python类型转换为类型转换器字符串。

下面是一个用于捕获日期年的类型转换器:
Django URLconf

使用register_converter()将以上类型转换器注册到URLconf。
Django URLconf

创建视图:

def get_year(request, year):
    return HttpResponse(str(year))

此时目录结构如下:
Django URLconf

启动Web服务,访问URL,如图所示。
Django URLconf

使用正则表达式

与Django 1.x一样,Django 2.0仍然可以使用正则表达式匹配URL,此时需要使用re_path()方法而不是path()。

Python的正则表达式支持对分组进行命名,语法格式为:(?P<name>pattern),其中name为分组名,pattern为匹配的正则表达式。

使用正则表达式对前面的URLconf进行重写效果如下:
Django URLconf

虽然可以使用未命名的正则表达式,例如使用([0-9]{4})替代(?P<year>[0-9]{4}),但是为了防止出现意外错误,推荐对分组命名。

另外需要注意,不要将命名正则表达式与未命名正则表达式混合使用,这样会造成未命名正则表达式丢失。

最后正则表达式可以嵌套使用,如:

re_path(r'comments/(?:page-(?P<page_number>\d+)/)?$', comments)

导入其他URLconf

对于现代Web应用程序来说,一个工程下通常会包含多个应用程序,每个应用程序包含很多URL,如果将这些URL都写在URLconf根模块中,那么URLconf将会变得非常臃肿,不利于维护。对于这种情况,常用的解决办法就是为每一个应用程序写一套独立的URLconf,而URLconf根模块通过使用include()方法将其他URLconf引用进来。

下面是Polls网站的mysite/urls.py
Django URLconf

当Django遇到include()方法时,URL匹配工作跳转进入被引用的URLconf进行验证。

使用include()方法还可以引用其他URL模式列表,例如:
Django URLconf

此时访问/credit/reports/时将会调用credit_views.report()视图方法。这样做的好处是当一个应用程序中多条URL的前缀相同时,在本例中extra_patterns中的URL都是以credit开头,可以简化URL模式字符串。

酷客教程相关文章:

赞(0)

评论 抢沙发

评论前必须登录!