Django项目开发实战
上QQ阅读APP看书,第一时间看更新

4.1 配置URL

URL是用户访问网站的起点,对于一个想要成功的网站来说,URL是非常重要的一部分。如果想要用户被网站吸引,必须确保网址足够简单、简短且友好。Django框架对URL的设计没有限制,允许开发者根据需要设计URL。

4.1.1 URL匹配

要设计应用程序的URL,可以创建URLconf模块,这个模块用于将URL路径表达式映射到Python函数。当用户从Django支持的站点请求页面时,执行顺序如下。

(1)Django确定要使用的根URLConf模块,这通常由ROOT_URLCONF设置,但如果传入的HttpRequest对象具有urlconf属性(由中间件设置),将使用其替代ROOT_URLCONF设置。

(2)Django加载URLConf模块,并在其中查找urlpatterns变量。

(3)Django按顺序遍历每个URL模式,一旦找到匹配的模式,就停止遍历。

(4)Django调用该模式映射的视图函数。

(5)如果没有任何URL模式匹配,或者在此过程中抛出异常,Django将调用适当的错误处理视图。例如:

分析:

  • 如果想从URL捕获值,则要使用尖括号。
  • 捕获的值可以包括转换器类型。
  • 对/categories/2018的请求会匹配到第二条规则,Django会调用方法views.category_detail(request,2018)。

可以使用命名的正则表达式组来捕获URL并将它们作为关键字参数传递给视图。在Python中,命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式。下面我们用正则模式来改写上面的例子:

以上代码实现的效果和前面的例子完全相同,只有一个细微的区别:捕获的值作为关键字参数而不是位置参数传递给视图函数。请求/categories/2018将会调用函数views.category_detail(request,categorey_id=2018)。

值得注意的是,无论正则表达式匹配什么类型,每个捕获的参数都作为普通Python字符串传递给视图函数。

在Django 2.1版本中,普通匹配使用path( )方法,正则匹配使用re_path( )方法来替代1.8版本中的url( )方法。在使用url( )方法匹配的时候需要注意Django的版本。

4.1.2 配置嵌套

urlpatterns可以包含其他URLconf模块,模块和模块之间会构成层级关系,示例代码如下:

注意,在上面的例子中,正则表达式并不包含“$”,多了“/”。每当Django遇到django.conf.urls.include( )方法时,它会删除与该点匹配的URL部分,并将剩余的字符串发送到包含的URLconf以进行进一步处理。

另一种可能性是include只包含url( )实例的列表,如下面的配置代码:

在上面的例子中,对/credit/reports/的请求会被credit_views.report视图函数处理。采用配置嵌套有助于URL的管理,删除冗余。

4.1.3 反向解析URL

在Django项目中,一个常见的需求是获得最终形式的URL字符串,将其嵌入生成的内容中,用来导航。

实现这个效果最简单的方式是在内容中写死URL,但这种方法费力,容易出错又不可扩展。在文档中写死业务URL会出现文档过时的问题。

Django提供了反向解析URL的功能来避免URL容易过时的问题。除此之外,这个功能还为开发提供了便捷,因为用户不再遍历所有项目源代码来搜索和替换过时的URL。

要做到反向解析URL,首先要对URL进行标识,如为URL起一个独一无二的名字。另外还需要知道正确的URL及对应的视图参数类型和值。这样,URLconf模块就有了两个作用:

  • 根据用户请求的URL,找到正确的视图函数,执行业务逻辑。
  • 标识相应的Django视图及传递给它的参数,获取相关的URL。

第一个作用在前面已经学习过了,现在来学习第二个作用。Django提供了用于执行URL反转的工具,这些工具在不同的层次中。

  • 在模板中,使用URL模板标签。
  • 在业务代码中,使用django.core.urlresolvers.reverse( )函数。
  • 在处理与Django模型实例相关URL的更高级代码中,使用get_absolute_url( )方法。

下面来看一个例子,还是使用之前用过的URLconf:

在模板中可以使用URL标签,带上签名设置的名字和参数,就能生成真实的连接。示例代码如下:

在视图代码中可以使用reverse( )方法,传入URLconf中定义的名字和参数,生成实际使用的链接。示例代码如下:

如果有一天请求详情品类的URL发生改变,那么只需要修改URLconf模块,其他的地方不用修改。