玩转Django 2.0
上QQ阅读APP看书,第一时间看更新

3.2 带变量的URL

在日常开发过程中,有时候一个URL可以代表多个不同的页面,如编写带有日期的URL,若根据前面的编写方式,按一年计算,则需要开发者编写365个不同的URL才能实现,这种做法明显是不可取的。因此,Django在编写URL时,可以对URL设置变量值,使URL具有多样性。

URL的变量类型有字符类型、整型、slug和uuid,最为常用的是字符类型和整型。各个类型说明如下。

• 字符类型:匹配任何非空字符串,但不含斜杠。如果没有指定类型,默认使用该类型。

• 整型:匹配0和正整数。

• slug:可理解为注释、后缀或附属等概念,常作为URL的解释性字符。可匹配任何ASCII字符以及连接符和下画线,能使URL更加清晰易懂。比如网页的标题是“13岁的孩子”,其URL地址可以设置为“13-sui-de-hai-zi”。

• uuid:匹配一个uuid格式的对象。为了防止冲突,规定必须使用破折号并且所有字母必须小写,例如075194d3-6885-417e-a8a8-6c931e272f00。

根据上述变量类型,在index的urls.py里添加带有字符类型、整型和slug的URL地址信息,代码如下:

     # index的urls.py
     from django.urls import path
     from . import views
     urlpatterns = [
         path('', views.index),
         # 添加带有字符类型、整型和slug的URL
         path('<year>/<int:month>/<slug:day>', views.mydate)
     ]

在URL中使用变量符号“<>”可以为URL设置变量。在括号里面以冒号划分为两部分,前面代表的是变量的数据类型,后面代表的是变量名,变量名可自行命名。上述代码对新增的URL设置了三个变量值,分别是<year>、<int:month>和<slug:day>,变量说明如下。

• <year>:变量名为year,数据格式为字符类型,与<str:year>的含义一样。

• <int:month>:变量名为month,数据格式为整型。

• <slug:day>:变量名为day,数据格式为slug。

然后在views.py中编写视图函数mydate的处理方法,代码如下:

     # views.py的mydate函数
     def mydate(request, year, month, day):
         return HttpResponse(str(year) +'/'+ str(month) +'/'+ str(day))

视图函数mydate有4个函数参数,其中参数year、month和day来自于URL的变量。URL的变量和视图函数的参数要一一对应,如果视图函数的参数与URL的变量对应不上,那么程序会抛出参数不相符的报错信息。启动项目,在浏览器上输入http://127.0.0.1:8000/2018/05/01,运行结果如图3-3所示。

图3-3 运行结果

在上述例子中,URL的变量分别代表年、月、日。从变量的数据类型可以看出,变量值只要符合数据格式都是合法的,使得某些变量值不符合日期格式要求。为了进一步规范日期格式,可以使用正则表达式限制URL的可变范围。正则表达式的URL编写规则如下:

在URL中引入正则表达式,首先导入re_path功能模块,正则表达式的作用是对URL的变量进行截取与判断,以小括号表示,每个小括号的前后可以使用斜杠或者其他字符将其分隔。以上述代码为例,分别将变量year、month和day以斜杠分割,每个变量以一个小括号为单位,在小括号内,可分为三部分,以(?P<year>[0-9]{4})为例进行介绍。

• ?P是固定格式。

• <year>为变量的编写规则。

• [0-9]{4}是正则表达式的匹配模式,代表变量的长度为4,只允许取0-9的值。

值得注意的是,如果URL的末端使用正则表达式,那么在该URL的末端应加上斜杠或者其他字符,否则正则表达式无法生效。例如上述例子的变量day,若在末端没有设置“.html”,则在浏览器上输入无限长的字符串,程序也能正常访问。