在Django的URLconf中使用命名组的方法
在我们想要捕获的URL部分上加上小括号,Django会将捕获的文本作为位置参数传递给视图函数。在更高级的用法中,还可以使用命名正则表达式组来捕获URL,并且将其作为关键字参数传给视图。
一个Python函数可以使用关键字参数或位置参数来调用,在某些情况下,可以同时进行使用。在关键字参数调用中,你要指定参数的名字和传入的值。在位置参数调用中,你只需传入参数,不需要明确指明哪个参数与哪个值对应,它们的对应关系隐含在参数的顺序中。
例如,考虑这个简单的函数:
defsell(item,price,quantity): print"Selling%sunit(s)of%sat%s"%(quantity,item,price)
为了使用位置参数来调用它,你要按照在函数定义中的顺序来指定参数。
sell('Socks','$2.50',6)
为了使用关键字参数来调用它,你要指定参数名和值。下面的语句是等价的:
sell(item='Socks',price='$2.50',quantity=6) sell(item='Socks',quantity=6,price='$2.50') sell(price='$2.50',item='Socks',quantity=6) sell(price='$2.50',quantity=6,item='Socks') sell(quantity=6,item='Socks',price='$2.50') sell(quantity=6,price='$2.50',item='Socks')
最后,你可以混合关键字和位置参数,只要所有的位置参数列在关键字参数之前。下面的语句与前面的例子是等价:
sell('Socks','$2.50',quantity=6) sell('Socks',price='$2.50',quantity=6) sell('Socks',quantity=6,price='$2.50')
在Python正则表达式中,命名的正则表达式组的语法是(?P<name>pattern),这里name是组的名字,而pattern是匹配的某个模式。
下面是一个使用无名组的URLconf的例子:
fromdjango.conf.urls.defaultsimport* frommysiteimportviews urlpatterns=patterns('', (r'^articles/(\d{4})/$',views.year_archive), (r'^articles/(\d{4})/(\d{2})/$',views.month_archive), )
下面是相同的URLconf,使用命名组进行了重写:
fromdjango.conf.urls.defaultsimport* frommysiteimportviews urlpatterns=patterns('', (r'^articles/(?P<year>\d{4})/$',views.year_archive), (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$',views.month_archive), )
这段代码和前面的功能完全一样,只有一个细微的差别:取的值是以关键字参数的方式而不是以位置参数的方式传递给视图函数的。
例如,如果不带命名组,请求/articles/2006/03/将会等同于这样的函数调用:
month_archive(request,'2006','03')
而带命名组,同样的请求就会变成这样的函数调用:
month_archive(request,year='2006',month='03')
使用命名组可以让你的URLconfs更加清晰,减少搞混参数次序的潜在BUG,还可以让你在函数定义中对参数重新排序。接着上面这个例子,如果我们想修改URL把月份放到年份的前面,而不使用命名组的话,我们就不得不去修改视图month_archive的参数次序。如果我们使用命名组的话,修改URL里提取参数的次序对视图没有影响。
当然,命名组的代价就是失去了简洁性:一些开发者觉得命名组的语法丑陋和显得冗余。命名组的另一个好处就是可读性强。