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”,则在浏览器上输入无限长的字符串,程序也能正常访问。