Django:重用代码以便在缺失对象上进行重定向

时间:2011-04-25 17:03:24

标签: python django django-views

我的网站的网址类似于

  

http://www.example.com/NY-2010/

     

http://www.example.com/NY-2010/location/

     

http://www.example.com/NY-2010/something-else/

     

http://www.example.com/Washington-2009/

     

http://www.example.com/Washington-2009/location/

     

http://www.example.com/Washington-2009/something-else/

等等。各种版本(如NY)有各种页面(如位置)。我使用像

这样的URLconf
url(r'^(?P<edition>[\d]+\-[\w]+)/$', views.home),
url(r'^(?P<edition>[\d]+\-[\w]+)/location/$', views.location),

在每个视图中,我必须获取当前版本。事实是,如果版本名称错误,我想重定向到最新版本。所以我做了类似

的事情
def home(request, edition):
    try:
        event = Edition.objects.get(name=edition)
    except ObjectDoesNotExist:
        return redirect(home, edition=Edition.latest())
    # If event was found I go on here

def location(request, edition):
    try:
        event = Edition.objects.get(name=edition)
    except ObjectDoesNotExist:
        return redirect(home, edition=Edition.latest())
    # If event was found I go on here

等等。当然有一些重复,我想尽量减少。我可以想到两种方式:

  • 使用get_objects_or_404()并自定义404视图或
  • 抽象函数中的公共部分。

两种方式的问题在于它们不允许我进行适当的重定向,即即使视图已更改,URL也将保持不变。有没有更好的方法来处理这些重定向?

编辑似乎我的问题不明确。特别是我不清楚我的意思是抽象函数中的公共部分。所以,我可以做的是以下

def get_edition_or_current(edition):
    try:
        event = Edition.objects.get(name=edition)
    except ObjectDoesNotExist:
        event = Edition.latest()
    return event

def home(request, edition):
    event = get_edition_or_current(edition)
    # I go on with a valid event here

def location(request, edition):
    event = get_edition_or_current(edition)
    # I go on with a valid event here

通过这种方式,我可以显示正确事件的视图,但我无法更改URL。要更改URL,视图必须返回重定向。我无法在get_edition_or_current内设置视图的返回值。

那么,Django如何实现get_object_or_404?好吧,它很简单,它引发了一个Http404异常,并在以后捕获它。但当然这仅适用于Http404异常,因为Django被指示捕获它们。

2 个答案:

答案 0 :(得分:1)

我认为最简单的方法是创建一个名为get_object_or_redirect的新效用函数,其作用与get_object_or_404相同。你甚至可以从django.shortcuts复制get_object_or_404的内容作为实现的起点,或者只是提取你上面的内容。

编辑:如评论中所述,重定向不能通过引发“异常”来完成,因此这实际上与get_object_or_404的工作方式不同。

答案 1 :(得分:1)

经过一番思考后,我找到了解决方案。

就足够了
  • 使用get_object_or_404
  • 自定义404视图,但直接将其设置为所需视图。而是将其设置为一个视图,该视图将重定向发送到正确的视图。

实施例

handler404 = views.error404

# Inside views

def error404(request):
    return redirect(...)