2011-06-23 38 views
16

Ekran için bir nesneyi aramak için Django sınıf tabanlı bir DetailView genel görünümü kullanıyorum. Belirli koşullar altında, nesneyi görüntülemek yerine, bunun yerine bir HTTP rediect'i dışarıda bırakmak ve yayınlamak istiyorum. Bunu yapmak için nasıl gittiğimi göremiyorum. Bir kullanıcı benim uygulamamdaki bir nesneyi vurduğunda, ancak kanonik URL'yi kullanmadan. Yani, örneğin, StackOverflow URL'ler hakkında biçiminde:Yönlendirmeden Genel Görünüm Ayrıntı GörünümüDuvar görünümü

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

örn:

Aslında seo_friendly_slug parçası olarak bir şey yazabilirsiniz ve nesne için doğru kanonik URL'ye yönlendirir
http://stackoverflow.com/questions/5661806/django-debug-toolbar-with-django-cms-and-django-1-3 

PK aracılığıyla baktım.

Bunu aynısını DetailView'umda yapmak isterim. Nesneyi geri alın, kurallı URL olduğunu ve öğenin get_absolute_url URL'sine yönlendirmediğini kontrol edin.

HttpResponseRedirect'i, bakılan nesneyi beklediği için get_object öğesinden geri dönemem. İçerik verisini beklediği için get_context_data'dan döndüremiyorum.

Belki sadece manuel bir görünüm yazmam gerekiyor, ancak bunun mümkün olup olmadığını bilen var mı?

Teşekkürler! Ludo.

cevap

15

Bu, DetailView için uygun değildir.

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) 

Yani sınıfta nesneyi alma ve kurma arasındaki URL kontrol ettik yeni olsun yöntemi sağlamaktır gerekir: Bunu yapmak için benziyor BaseDetailView get yöntemini geçersiz kılmak gerekir bağlam. Eğer gerçekte bunun için genel bir görünümünü kullanarak, ama Biliyor değer mi sorusu sorulabilir hale işlevselliği çok ağır basan sonuçlanması dolayısıyla

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) 

: gibi bir şey. Rolo cevabı ve yorumlar üzerine Gelişmekte

+1

Diğer durumlarda burada ebeveyn alma yöntemini çağırabilirsiniz. Daha temiz olurdu. Özel işlevsellik için genişletilecek sınıf tabanlı genel görünümler olduğundan tamamen buna değer. – vimukthi

+1

Yaklaşımınız ile ilgili iyi olan şey, eğer BaseDetailView.get uygulaması değiştiğinde endişelenmenize gerek olmamasıdır, ancak olumsuzluk, her istek için nesne alma işlemini iki kez yapmamız gerektiğidir. potansiyel performans/ölçeklenebilirlik isabetine değer. – Rolo

+0

'get_object' için çift vuruştan kaçınmak için, kendi sınıfınızda geçersiz kılabilir ya da bir kontrolle önsözleştirebilirsiniz' eğer hasattr (self, 'object', None) '; Çeki başarılı olursa "self.object" i döndürürseniz, aksi takdirde ebeveynin "get_object" i çağırılır. Tam olarak @Raumkraut uygulandığı gibi (https://stackoverflow.com/a/12858110). – interDist

10

, bu amaca hizmet için aşağıdaki jenerik görüntüsü geldi:

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

Bu normaldir DetailView aynı şekilde kullanılır ve herhangi bir model için çalışması gerektiğini hangi get_absolute_url'u doğru uygular.

İlgili konular