如何处理URL参数类型?
想象一下,有一个应用程序,它的 url.py
文件是这样的:
urlpatterns = patterns('',
url(r'^$', views.index),
url(r'^double/(?P<number>\d+)/$', views.double),
)
还有这个 views.py
文件:
def double(request, number=42):
return HttpResponse(2*number)
显然,我希望 number
总是被当作整数来处理。当我查询 /double/5/
时,我总是希望得到 10
,而不是 55
。
在 Django 的网址中,有没有好的方法来处理参数的类型呢?
3 个回答
0
Anto,
我觉得你的问题主要和网址有关。(?P<number>\d+)
是一种正则表达式,它的意思是 \d
只允许数字,这和 [0-9]
是一样的。+
符号表示需要一个或多个数字。所以如果你尝试插入像 double/notanumber/
这样的内容,它就不行。
知道这些之后,你可以放心地假设:
1: number 总是会有一个值
2: number 总是会是一个整数(即使 Django 返回的是 Unicode 格式)
我对你的函数做了一个小改动:
def double(request, number): # removed the =42 because number can never be empty
return HttpResponse(2 * int(number)) # Converted your number to an integer
1
这个讨论串提到自动转换并不是一个好主意:
要注意,自动转换其实不是个好办法。例如,我博客的下一个版本会把像 2008/2/25/ 这样的 URL 转换成 2008/02/25/,因为我想要一个标准的格式。所以我需要知道 \d{1,2} 是否匹配一到两个数字,即使第一个数字是 0。自动转换成整数会失去这个能力(而且很容易想到其他类似的情况)。所以你需要能够进行配置。
它还建议了一种基于装饰器的解决方案,但我并不是很相信,这听起来有点麻烦:
解决你问题的一种方法是写一个装饰器,它接受一个类型列表(加上类似 None 的东西表示“无所谓”),然后在调用你的函数之前,自动把第 N 个参数转换成列表中第 N 个元素的类型。
2
这里有一个基于装饰器的解决方案:
def param_type(**type_spec):
def deco(f):
def view(request, **kwargs):
for k, type_ in type_spec.items():
kwargs[k] = type_(kwargs[k])
return f(request, **kwargs)
return view
return deco
@param_type(number=int)
def double(request, number=42):
return HttpResponse(2*number)