Django:重用代码以重定向丢失的对象
我有一个网站,其网址如下
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/
等等在。不同版本(例如纽约)有不同的页面(例如位置)。我使用 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/
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为最简单的方法是创建名为
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 asget_object_or_404
. You could probably even copy the contents ofget_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.
经过一番思考,我找到了解决方案。 就足够了
get_object_or_404
例子
After some more thought, I have found a solution. It is enough to
get_object_or_404
Example