Django:任意数量未命名的urls.py参数

22 投票
5 回答
6448 浏览
提问于 2025-04-11 09:32

我有一个Django模型,里面有很多字段,还有超过20000行数据。为了让网址更易读,并且能把这个大列表分成任意的小列表,我想要一个看起来像这样的URL:

/browse/<name1>/<value1>/<name2>/<value2>/ .... etc ....

在这个URL中,'name'对应模型的一个属性,而'value'是这个属性的搜索条件。每个“name”就像一个类别,用来返回那些类别匹配的模型实例的子集。

虽然可以用GET参数来处理这个问题,但我更喜欢让网址更易读,这样对用户和搜索引擎都更友好。这些网址子集会嵌入在每个显示这个模型的页面上,所以为了让网址看起来更好,花点力气是值得的。

理想情况下,每对name/value都会作为参数传递给视图函数,参数名分别是name1name2等等。不过,我觉得通过正则表达式匹配的文本来定义命名模式是不可能的。我这样想对吗?

所以,看起来我需要做类似这样的事情:

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 个回答

1

我有一个替代的解决方案,虽然和之前的差不多,但更精炼了一些:

url(r'^my_app/(((list\/)((\w{1,})\/(\w{1,})\/(\w{1,3})\/){1,10})+)$'

我使用了没有名字的URL参数和一个重复的正则表达式。为了避免出现“不是有效的正则表达式:重复多次”的错误,我在列表的开头放了一个单词。

我还在处理接收这个列表的视图。不过我想我会通过args或kwargs来处理……现在还不能确切说清楚。

这是我的一点想法

3

我同意亚当的看法,但我觉得在urls.py文件中的写法应该是:

... r'^browse/(?P<match>.+)/$' ...

这里的'\w'只会匹配字母和数字等“单词”字符,而'.'则可以匹配任何东西。

15

你可以考虑一种方法,就是在网址模式的部分匹配整个可能的值字符串,然后在你的视图中提取出具体的部分。举个例子:

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
    ...

我对我用的正则表达式没有保证,但我想你明白我的意思。

(我编辑了一下,试图修正正则表达式。)

撰写回答