多个Django应用使用相同的URL模式

1 投票
3 回答
4205 浏览
提问于 2025-04-17 16:01

我想让两个应用程序使用相同的URL模式。我希望避免像domain.com/pages/something-here或domain.com/blog/something-there这样的应用特定的路径。

我试过这样做:

# urls.py
urlpatterns = patterns('',
    url(r'^$', 'my.homepage.view'),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^', include('pages.urls')),
    url(r'^', include('blog.urls')),
)

# pages/urls.py
urlpatterns = patterns('',
    url(r'^(.+)/$', views.page),
)

# blog/urls.py
urlpatterns = patterns('',
    url(r'^(.+)/$', views.post),
)

我的代码不管怎么写,先引入哪个(这里是pages.urls)就能正常工作,其他的URL(比如博客的)就会出现404错误。

提前谢谢你们!

编辑:我这样做了:在settings.py同一目录下创建了一个glue.py文件。它将处理我的主页和这个调度视图:

def dispatcher(request, slug):
    try:
        page = get_object_or_404(Page, slug=slug)
        return render(request, 'pages/page.html', {'page': page})
    except:
        post = get_object_or_404(Post, slug=slug)
        return render(request, 'blog/post.html', {'post': post})

我不知道这样是否合适。希望有更好的方法。

谢谢大家的评论。

3 个回答

-1

你希望这个功能怎么实现呢?它们都在用同一个网址(这当然会造成问题)。用户怎么才能访问到“页面”而不是“博客”,或者反过来呢?

一般来说,你不能在网址模式中有重叠的网址(除非加上额外的数据)。

编辑:

所以你想让第一个应用检查一下它是否有可以匹配这个网址的视图,如果没有再让第二个应用接手?你可以做一些复杂的事情,比如写一个“视图匹配器”来实现你想要的,但其实有更简单的解决办法。

最简单的方法是修改其中一个应用的 slug 生成函数。让其中一个应用使用不同于下划线的分隔符,或者总是在 slug 后面加上应用的名字。这样你就能通过网址来区分页面和博客,比如页面的网址是“some-slug-page”,而博客的网址是“some-slug-blog”,这样你就可以为它们写出网址模式。如果你不想加上整个网址,也可以只加上第一个字母,或者你想要的任何东西。

只要想一个你觉得合适的方法来为每个应用生成网址,这样通过阅读网址就能知道这个页面属于哪个应用。

0

这个问题的原因在于,Django处理网址的顺序是有讲究的,也就是说,首先匹配到的那个网址就会被使用。在你的情况中,来自博客应用的网址永远不会被检查,因为Django在处理页面的包含行时已经找到了匹配的网址。

另外,Django的网址模块并不知道某个页面或博客文章是否存在,因为在你的应用中,这个是通过查询数据库来判断的。

网址模块只是执行与第一个匹配的正则表达式相关联的视图。

你应该改变一下你的逻辑,比如在博客网址前加上“blog/”(这样有什么问题呢?)

   url(r'^blog/', include('blog.urls')),
   url(r'^', include('pages.urls')),

注意,我把博客的网址放在了前面,因为大多数通用的正则表达式应该总是最后被Django的网址解析器尝试。

另外,你也可以写一个代理视图,尝试同时处理博客文章和页面,但我觉得这不是最好的方法。

1

我不知道这是不是更好的答案。不过,如果你满足以下情况的话……

  1. 你的Django应用是基于Django模板来渲染的。

  2. 你提到的那个网址,不需要直接在浏览器里输入地址来访问。

那么,也许你可以考虑使用网址命名空间和模板重定向。

https://docs.djangoproject.com/en/1.11/topics/http/urls/#url-namespaces

撰写回答