如何处理URL参数类型?

6 投票
3 回答
1208 浏览
提问于 2025-04-18 13:43

想象一下,有一个应用程序,它的 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)

撰写回答