【问题标题】:Manage Increasingly complex Django URL views efficiently? (urls.py)有效地管理日益复杂的 Django URL 视图? (urls.py)
【发布时间】:2010-02-02 20:08:27
【问题描述】:

所以,我有这个 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'),

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

# 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'),

然后,对于 Teams 再次类似。 . .

# 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 介绍的减少重复复杂性的聪明方法吗?

【问题讨论】:

    标签: python django django-urls


    【解决方案1】:

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

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

    【讨论】:

    • 你有一些正确的观点 - URL 用于唯一标识资源,而不是用于过滤。
    • 是的,这就是我在问题的底部附近得到的结果:几乎绕过urls.py 并从视图函数中的请求字符串中解析出查询参数。我不确定 django-filter 是我想要的工具,但感谢您确认我认为的解决方案。 . .
    • 但是在您的解决方案中,您仍然使用 URL,只是没有使用 django 的 URL 路由机制,而是发明了自己的。使用 GET 参数,您的代码将缩短一半,清晰两倍。
    【解决方案2】:

    让我们专注于这一点:

        # 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 的答案,因为您可能在这里遇到了一些元问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多