2011-06-23 79 views
16

DjangoのクラスベースのDetailView汎用ビューを使用して表示するオブジェクトを検索しています。特定の状況下では、オブジェクトを表示するのではなく、代わりにHTTP rediectを取り消して発行したいと考えています。私はこれをやってどうやって行くのか分かりません。これは、ユーザーがアプリでオブジェクトをヒットしたときのものですが、標準URLは使用しません。したがって、たとえば、StackOverflowののURLの形式をとる:Djangoの汎用ビューDetailViewからリダイレクト

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

例:

あなたが実際にseo_friendly_slugの一環として、何も入力することができますし、オブジェクトの正しい正規のURLにリダイレクトされます
http://stackoverflow.com/questions/5661806/django-debug-toolbar-with-django-cms-and-django-1-3 

PKを介して見上げた。

私はDetailViewで同じことをしたいと思います。オブジェクトを取得し、正規のURLであることを確認し、アイテムのget_absolute_url URLにリダイレクトしない場合は、そのオブジェクトを取得します。

get_objectでHttpResponseRedirectを返すことはできません。これは、検索されたオブジェクトを期待しているためです。コンテキストデータを期待しているだけなので、get_context_dataから返すことはできません。

多分私はマニュアルビューを書く必要があるかもしれませんが、誰かがそれが可能かどうか分かっていたのでしょうか?

ありがとうございます!

ルド。

答えて

15

これは、DetailViewにはあまり適していません。

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) 

は、だからあなたのクラスでは、オブジェクトをフェッチし、セットアップの間でURLのチェックをした新しいgetメソッドを提供する必要があると思います。これを行うには次のようになりますBaseDetailViewのgetメソッドをオーバーライドする必要があります文脈あなたはそれが実際にこのため、一般的なビューを使用しますが、youknow価値があるかどうかは疑問となった機能の大半をオーバーライドして終了したよう

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) 

:ような何か。ロロの回答やコメントに開発

+1

ここでelseの場合は、親のgetメソッドを呼び出すことができます。それはずっとすっきりしているだろう。カスタム機能のためにクラスベースの汎用ビューが拡張されているので、それは価値があります。 – vimukthi

+1

あなたのアプローチが良い点は、BaseDetailView.getの実装が変更されても心配する必要はありませんが、欠点はすべての要求に対してオブジェクト取得を2回実行する必要があることです。潜在的なパフォーマンス/スケーラビリティヒットの価値があります。 – Rolo

+0

'get_object'へのダブルヒットを避けるために、自分のクラスやmixinでそれを上書きして' if hasattr(self、 'object'、None) 'というチェックを書いても構いません。チェックが成功すれば 'self.object'を返し、そうでなければ親の' get_object'を呼び出します。 @Raumkrautが実装されたのとまったく同じです(https://stackoverflow.com/a/12858110)。 – interDist

10

は、私は、この目的を果たすために、次の汎用ビューを思い付いた:

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を正しく実装しています。

関連する問題