有效地管理越来越复杂的Django URL视图? (urls.py)

时间:2010-02-02 20:08:27

标签: python django django-urls

所以,我有这个Django应用程序,我不断添加新功能,以提供更细粒度的数据视图。为了快速了解问题,这里是urls.py的一个子集:

# Simple enough . . .
(r'^$', 'index'),
(r'^date/(?P<year>\d{4})$', 'index'),
(r'^date/(?P<year>\d{4})-(?P<month>\d{2})$', 'index'),
(r'^date/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})$', 'index'),
(r'^page/(?P<page>\d+)$', 'index'),

所以,是的,默认视图,日期视图,分页视图,然后是用户特定网址的类似设置:

# user
(r'^user/(?P<username>\w+)$', 'index_username'),
(r'^user/(?P<username>\w+)/date/(?P<year>\d{4})$', 'index_username'),
(r'^user/(?P<username>\w+)/date/(?P<year>\d{4})-(?P<month>\d{2})$', 'index_username'),
(r'^user/(?P<username>\w+)/date/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})$', 'index_username'),
(r'^user/(?P<username>\w+)/page/(?P<page>\d+)$', 'index_username'),

然后,类似于团队。 。

# Team View
(r'^team/(?P<team>\w+)$', 'index'),
(r'^team/(?P<team>\w+)/date/(?P<year>\d{4})$', 'index'),
(r'^team/(?P<team>\w+)/date/(?P<year>\d{4})-(?P<month>\d{2})$', 'index'),
(r'^team/(?P<team>\w+)/date/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})$', 'index'),
(r'^team/(?P<team>\w+)/page/(?P<page>\d+)$', 'index'),

现在,我想添加一个“搜索”视图,而且我认为将它添加到上述许多URL的末尾会很好,所以我可以点击:

/search/foo
/user/fred/date/2010-01/search/baz

然后我可以将搜索参数传递给视图,这可能会适当地约束结果。

但是,如果我想将其应用于用户,团队和最新视图,我已经在urls.py添加了12个新行。每次我添加另一个潜在的视图选项(比如分页搜索结果?)。 。 。它只是觉得应该有更好的方式。

从我的研究中,答案似乎是:
1)urls.py内的更广泛匹配,并使视图函数解析查询字符串 2)也许urls.py中的一些更强大的正则表达式逻辑可以说“如果这种模式匹配,则在传递给视图函数时包括参数”多次。但这可能是噩梦般的维持。

有没有人想出一个更优雅的解决方案来优雅地管理复杂的URL?我认为在某一点上,最简单的方法是将参数匹配逻辑传递给视图本身,以便从查询字符串中解析出参数。因此,在视图的顶部附近,我可能会有一些看起来像这样的代码:

# Date Queries
re_ymd = re.compile('date/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})')
re_ym = re.compile('date/(?P<year>\d{4})-(?P<month>\d{2})')
re_y = re.compile('date/(?P<year>\d{4})')
if( re_ymd.search(qs) ):
    year = re_ymd.search(qs).group('year')
    month = re_ymd.search(qs).group('month')
    day = re_ymd.search(qs).group('day')
elif( re_ym.search(qs) ):
    year = re_ym.search(qs).group('year')
    month = re_ym.search(qs).group('month')
elif( re_y.search(qs) ):
    year = re_y.search(qs).group('year')

# Pagination queries
re_p = re.compile('page/(?P<page>\d+)')
if( re_p.search(qs) ):
    page = re_p.search(qs).group('page')

# Search queries
re_s = re.compile('search/(?P<search>\w+)')
if( re_s.search(qs) ):
    search = re_s.search(qs).group('search')

那么,这是否是一种降低我urls.py引入的重复复杂性的聪明方法?

2 个答案:

答案 0 :(得分:3)

为什么不使用GET参数或django-filter,如果您只是对结果进行过滤/分组不同?

我看到使用GET的原因是它更容易实现,并且看起来更清晰:在URL解决方案/ search / foo / user / bar /和/ user / bar / search / foo /中有2个名称完全相同的内容。在GET参数解决方案中它的所有相同的页面。

答案 1 :(得分:0)

让我们关注这一点:

    # Simple enough . . .
    (r'^$', 'index'),
    (r'^date/(?P<year>\d{4})$', 'index'),
    (r'^date/(?P<year>\d{4})-(?P<month>\d{2})$', 'index'),
    (r'^date/(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})$', 'index'),
    (r'^page/(?P<page>\d+)$', 'index'),

我认为有一些:

    def index(year=2010, month=2, day=2, page=0):
        # whatever

那么,为什么不将你的正则表达式合二为一,例如

     r'^date/(?P<year>\d{4})(-(?P<month>\d{2})(-(?P<day>\d{2}))?)?$

我还没试过,但我很确定这样的东西会起作用。

编辑:

虽然重写正则表达式可行,但请看看Ofri Raviv的答案,因为这可能是你在这里遇到了一些元问题。