在django中处理遗留URL的最佳方法

时间:2014-05-06 07:58:09

标签: django

我正在制作一个重要的新闻发布平台。基本上用django从零开始重建所有东西。现在我们已经准备好启动了,我需要处理遗留的URL重定向。考虑到我必须处理成千上万的遗留网址,最好的方法是什么?

逻辑应该像这样工作:如果匹配的现有网址/视图都没有通过遗留重定向网址模式/视图运行该网址,以查看它是否可以在返回404错误之前提供一些重定向到新网址。

我该怎么做?

3 个答案:

答案 0 :(得分:1)

很棒,通过使用自定义中间件实现了这一点:

from django.http import Http404
from legacy.urls import urlpatterns

class LegacyURLsMiddleware(object):

    def process_response(self, request, response):
        if response.status_code != 404:
            return response
        for resolver in urlpatterns:
            try:
                match = resolver.resolve(request.path[1:])
                if match:
                    return match.func(request, *match.args, **match.kwargs)
            except Http404:
                pass
        return response

只需将此中间件添加为MIDDLEWARE_CLASSES列表中的最后一个中间件即可。然后在遗留应用程序中使用urls.py文件来声明将处理永久重定向的旧URL和视图。请勿将旧网址包含在主网址结构中。这个中间件为你做了,但有点不同。

答案 1 :(得分:0)

您可能想要创建一个后备视图,该视图将尝试处理您的模式未处理的任何网址。我看到两个选择。

  1. 只需创建一个“默认”模式。这种模式很重要 是你的urlpatterns中的最后一个!

    你的urls.py中的

    urlpatterns = patterns(
        '',
        # all your patterns
        url(r'^.+/', 'app.views.fallback')
    )
    
    在你的views.py中

    from django.http.response import HttpResponseRedirect, Http404
    
    def fallback(request):
        if is_legacy(request.path):
            return HttpResponseRedirect(convert(request.path))
        raise Http404
    
  2. 创建自定义http 404处理程序。

    你的urls.py中的

    handler404 = 'app.views.fallback'
    
    你的views.py中的

    from django.http.response import HttpResponseRedirect
    from django.views.defaults import page_not_found
    
    def fallback(request):
        if is_legacy(request.path):
            return HttpResponseRedirect(convert(request.path))
        return page_not_found(request)
    

    它似乎是一个更好的解决方案,但它只有在您将DEBUG设置为False并提供自定义404模板时才有效。

答案 2 :(得分:0)

使用雅各布的django-multiurl。有一天django ticket可以解决这个问题,但是现在django-multiurl效果非常好。

在:

# urls.py
urlpatterns = patterns('',
    url('/app/(\w+)/$', app.views.people),
    url('/app/(\w+)/$', app.views.place),  # <-- Never matches
)

后:

# urls.py
from multiurl import multiurl, ContinueResolving
from django.http import Http404

urlpatterns = patterns('', multiurl(
    url('/app/(\w+)/$', app.views.people), # <-- Tried 1st
    url('/app/(\w+)/$', app.views.place),  # <-- Tried 2nd (only if 1st raised Http404)
    catch=(Http404, ContinueResolving)
))