从Django中的Generic View DetailView重定向

Lud*_*udo 16 generics django seo views

我正在使用Django基于类的DetailView通用视图来查找要显示的对象.在某些情况下,我希望退出并发出HTTP重定向,而不是显示对象.我看不出我是怎么做的.它适用于用户点击我的应用中的对象但不使用规范网址的情况.因此,例如,在StackOverflow URL上采用以下形式:

http://stackoverflow.com/<content_type>/<pk>/<seo_friendly_slug>
Run Code Online (Sandbox Code Playgroud)

例如:

http://stackoverflow.com/questions/5661806/django-debug-toolbar-with-django-cms-and-django-1-3
Run Code Online (Sandbox Code Playgroud)

您实际上可以键入任何内容作为seo_friendly_slug部分,它会将您重定向到通过PK查找的对象的正确规范URL.

我希望在我的DetailView中也这样做.检索对象,检查它是否是规范URL,如果没有,则重定向到项目的get_absolute_url URL.

我无法在get_object中返回HttpResponseRedirect,因为它期望查找对象.我似乎无法从get_context_data返回它,因为它只是期望上下文数据.

也许我只需要写一个手动视图,但我想知道是否有人知道它是否可能?

谢谢!

卢多.

Rol*_*olo 15

这不是DetailView的自然选择.为此,您需要覆盖BaseDetailView的get方法,如下所示:

class BaseDetailView(SingleObjectMixin, View):
    def get(self, request, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)
Run Code Online (Sandbox Code Playgroud)

因此,在您的类中,您需要提供一个新的get方法,该方法在获取对象和设置上下文之间进行URL检查.就像是:

def get(self, request, **kwargs):
    self.object = self.get_object()
    if self.request.path != self.object.get_absolute_url():
        return HttpResponseRedirect(self.object.get_absolute_url())
    else:
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)
Run Code Online (Sandbox Code Playgroud)

当你最终覆盖了如此多的功能时,它是否值得为此实际使用通用视图值得怀疑,但你知道.


Rom*_*løk 10

根据Rolo的回答和评论,我提出了以下通用视图来实现此目的:

from django import http
from django.views import generic


class CanonicalDetailView(generic.DetailView):
    """
        A DetailView which redirects to the absolute_url, if necessary.
    """
    def get_object(self, *args, **kwargs):
        # Return any previously-cached object
        if getattr(self, 'object', None):
            return self.object
        return super(CanonicalDetailView, self).get_object(*args, **kwargs)

    def get(self, *args, **kwargs):
        # Make sure to use the canonical URL
        self.object = self.get_object()
        obj_url = self.object.get_absolute_url()
        if self.request.path != obj_url:
            return http.HttpResponsePermanentRedirect(obj_url)
        return super(CanonicalDetailView, self).get(*args, **kwargs);
Run Code Online (Sandbox Code Playgroud)

它的使用方法与普通的DetailView相同,适用于任何get_absolute_url正确实现的模型.