Django:重用代码以重定向丢失的对象

发布于 2024-11-03 09:37:06 字数 2478 浏览 1 评论 0原文

我有一个网站,其网址如下

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 /

等等在。不同版本(例如纽约)有不同的页面(例如位置)。我使用 URLconfs,就像

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 被指示捕获它们。

I have a site whose URLs look like

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/

and so on. There are various pages (like location) for various editions (like NY). I use URLconfs like

url(r'^(?P<edition>[\d]+\-[\w]+)/

In each of the views I have to fetch the current edition. The fact is, if the edition name is wrong, I want to redirect to the latest edition. So I do something like

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

and so on. Of course there is some duplication that I'd like to minimize. I can think of two ways:

  • use get_objects_or_404() and customize the 404 view, or
  • abstract the common part in a function.

The problem with both ways is that they do not allow me to do a proper redirect, that is, the URL will remain the same even if the view was changed. Is there a better way to handle these redirects?

EDIT It seems my question is not clear. In particular it is not clear what I mean by abstract the common part in a function. So, what I could do is the following

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

In this way I can display the view for a proper event, but I cannot change the URL. To change the URL, the view must return a redirect. I cannot set the return value for the view from inside get_edition_or_current.

So, how does Django implements get_object_or_404? Well, it is simple, it raises an Http404 exception, and catches it later. But of course this only works for Http404 exceptions, because Django is instructed to catch them.

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

In each of the views I have to fetch the current edition. The fact is, if the edition name is wrong, I want to redirect to the latest edition. So I do something like


and so on. Of course there is some duplication that I'd like to minimize. I can think of two ways:

  • use get_objects_or_404() and customize the 404 view, or
  • abstract the common part in a function.

The problem with both ways is that they do not allow me to do a proper redirect, that is, the URL will remain the same even if the view was changed. Is there a better way to handle these redirects?

EDIT It seems my question is not clear. In particular it is not clear what I mean by abstract the common part in a function. So, what I could do is the following


In this way I can display the view for a proper event, but I cannot change the URL. To change the URL, the view must return a redirect. I cannot set the return value for the view from inside get_edition_or_current.

So, how does Django implements get_object_or_404? Well, it is simple, it raises an Http404 exception, and catches it later. But of course this only works for Http404 exceptions, because Django is instructed to catch them.

, views.location),

In each of the views I have to fetch the current edition. The fact is, if the edition name is wrong, I want to redirect to the latest edition. So I do something like

and so on. Of course there is some duplication that I'd like to minimize. I can think of two ways:

  • use get_objects_or_404() and customize the 404 view, or
  • abstract the common part in a function.

The problem with both ways is that they do not allow me to do a proper redirect, that is, the URL will remain the same even if the view was changed. Is there a better way to handle these redirects?

EDIT It seems my question is not clear. In particular it is not clear what I mean by abstract the common part in a function. So, what I could do is the following

In this way I can display the view for a proper event, but I cannot change the URL. To change the URL, the view must return a redirect. I cannot set the return value for the view from inside get_edition_or_current.

So, how does Django implements get_object_or_404? Well, it is simple, it raises an Http404 exception, and catches it later. But of course this only works for Http404 exceptions, because Django is instructed to catch them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半暖夏伤 2024-11-10 09:37:06

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

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

I think the simplest way to do this would be to create new utility function called get_object_or_redirect in the same vein as get_object_or_404. You could probably even copy the contents of get_object_or_404 from django.shortcuts as a starting point for your implementation, or just extract out what you have above.

EDIT: as noted in the comments, a redirect cannot be done via raising an "exception," so this really can't work the same as get_object_or_404.

泪冰清 2024-11-10 09:37:06

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

  • 使用get_object_or_404
  • 自定义404视图 ,但不能直接将其设置为所需的视图。相反,将其设置为一个视图,该视图将发送重定向到正确的视图。

例子

handler404 = views.error404

# Inside views

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

After some more thought, I have found a solution. It is enough to

  • use get_object_or_404
  • customize the 404 view, but not directly set it to the desired view. Rather, set it to a view which will send a redirect to the correct view.

Example

handler404 = views.error404

# Inside views

def error404(request):
    return redirect(...)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文