【问题标题】:Redirect from Generic View DetailView in Django从 Django 中的通用视图 DetailView 重定向
【发布时间】:2011-09-21 08:16:36
【问题描述】:

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

http://stackoverflow.com/<content_type>/<pk>/<seo_friendly_slug>

例如:

http://stackoverflow.com/questions/5661806/django-debug-toolbar-with-django-cms-and-django-1-3

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

我希望在我的 DetailView 中做同样的事情。检索对象,检查它是否是规范 URL,如果不是,则重定向到项目的 get_absolute_url URL。

我无法在 get_object 中返回 HttpResponseRedirect,因为它正在等待查找的对象。我似乎无法从 get_context_data 返回它,因为它只需要上下文数据。

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

谢谢!

卢多。

【问题讨论】:

    标签: django generics seo views


    【解决方案1】:

    这不适合 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)
    

    因此,在您的类中,您需要提供一个新的 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)
    

    由于您最终覆盖了如此多的功能,因此实际上是否值得为此使用通用视图值得怀疑,但您知道。

    【讨论】:

    • 这里的 else 情况下,你可以只调用父母的 get 方法。会干净很多。这是完全值得的,因为基于类的通用视图可以扩展自定义功能。
    • 你的方法的好处是我们不需要担心 BaseDetailView.get 的实现是否发生变化,但缺点是我们需要为每个请求进行两次对象检索,对我来说,这不值得潜在的性能/可扩展性影响。
    • 为了避免对get_object 的双重打击,您可以在自己的类或mixin 中覆盖它,并在前面加上检查if hasattr(self, 'object', None);如果检查成功,则返回self.object,否则调用父级的get_object。与 @Raumkraut 实现的完全相同 (stackoverflow.com/a/12858110)。
    【解决方案2】:

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

    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);
    

    这与普通 DetailView 的使用方式相同,并且应该适用于正确实现 get_absolute_url 的任何模型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-06
      • 2021-09-25
      • 1970-01-01
      • 2020-06-22
      • 2020-02-16
      • 2016-08-22
      • 1970-01-01
      • 2018-06-04
      相关资源
      最近更新 更多