Django:任意数量未命名的urls.py参数
我有一个Django模型,里面有很多字段,还有超过20000行数据。为了让网址更易读,并且能把这个大列表分成任意的小列表,我想要一个看起来像这样的URL:
/browse/<name1>/<value1>/<name2>/<value2>/ .... etc ....
在这个URL中,'name'对应模型的一个属性,而'value'是这个属性的搜索条件。每个“name”就像一个类别,用来返回那些类别匹配的模型实例的子集。
虽然可以用GET参数来处理这个问题,但我更喜欢让网址更易读,这样对用户和搜索引擎都更友好。这些网址子集会嵌入在每个显示这个模型的页面上,所以为了让网址看起来更好,花点力气是值得的。
理想情况下,每对name/value都会作为参数传递给视图函数,参数名分别是name1
、name2
等等。不过,我觉得通过正则表达式匹配的文本来定义命名模式是不可能的。我这样想对吗?
所以,看起来我需要做类似这样的事情:
urlpatterns = patterns('',
url(r'^browse/(?:([\w]+)/([\w]+)/)+$', 'app.views.view', name="model_browse"),
)
这似乎应该能匹配任何两对name/value。不过,虽然它成功匹配了,但只把最后一对name/value作为参数传递给视图函数。我猜是因为每次匹配都覆盖了之前的匹配。根据我对包含的(?:...)+的猜测,我尝试了一个简单的重复模式:
urlpatterns = patterns('',
url(r'^browse/([\w]+/)+$', 'app.views.view', name="model_browse"),
)
... 但还是遇到同样的问题,这次*args
只包含最后一个匹配的模式。
这是Django的URL调度器的限制,还是Python的正则表达式支持的问题?看起来这两种方法都应该能工作。有没有办法在不把每个可能的模型属性硬编码到URL中作为可选(.*)模式的情况下实现这个?
5 个回答
我有一个替代的解决方案,虽然和之前的差不多,但更精炼了一些:
url(r'^my_app/(((list\/)((\w{1,})\/(\w{1,})\/(\w{1,3})\/){1,10})+)$'
我使用了没有名字的URL参数和一个重复的正则表达式。为了避免出现“不是有效的正则表达式:重复多次”的错误,我在列表的开头放了一个单词。
我还在处理接收这个列表的视图。不过我想我会通过args或kwargs来处理……现在还不能确切说清楚。
这是我的一点想法
我同意亚当的看法,但我觉得在urls.py文件中的写法应该是:
... r'^browse/(?P<match>.+)/$' ...
这里的'\w'只会匹配字母和数字等“单词”字符,而'.'则可以匹配任何东西。
你可以考虑一种方法,就是在网址模式的部分匹配整个可能的值字符串,然后在你的视图中提取出具体的部分。举个例子:
urlpatterns = patterns('',
url(r'^browse/(?P<match>.+)/$', 'app.views.view', name='model_browse'),
)
def view(request, match):
pieces = match.split('/')
# even indexed pieces are the names, odd are values
...
我对我用的正则表达式没有保证,但我想你明白我的意思。
(我编辑了一下,试图修正正则表达式。)