2011-06-23 53 views
16

Tôi đang sử dụng lớp học của Chế độ xem tổng quan DetailView của Django để tìm kiếm một đối tượng để hiển thị. Trong một số trường hợp, thay vì hiển thị đối tượng, tôi muốn quay lại và phát hành một HTTP rediect thay thế. Tôi không thể thấy cách tôi làm việc này. Đó là khi người dùng truy cập một đối tượng trong ứng dụng của tôi, nhưng không sử dụng URL chuẩn. Vì vậy, ví dụ, trên URL StackOverflow mang hình thức:Chuyển hướng từ Chế độ xem chi tiết chung Xem trong Django

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

ví dụ:

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

Bạn thực sự có thể gõ bất cứ điều gì như là một phần seo_friendly_slug và nó sẽ chuyển hướng bạn đến URL kinh điển chính xác cho các đối tượng nhìn lên qua PK.

Tôi muốn làm tương tự trong DetailView của mình. Truy lục đối tượng, kiểm tra xem đó có phải là URL chuẩn hay không và nếu không chuyển hướng đến URL get_absolute_url của mục.

Tôi không thể trả lại một HttpResponseRedirect trong get_object, vì nó đang chờ đối tượng tra cứu. Tôi dường như không thể trả lại nó từ get_context_data, vì nó chỉ mong đợi dữ liệu ngữ cảnh.

Có lẽ tôi chỉ cần viết chế độ xem thủ công, nhưng tôi tự hỏi liệu có ai biết nếu có thể không?

Cảm ơn!

Ludo.

Trả lời

15

Đây không phải là sự phù hợp tự nhiên cho DetailView. Để làm điều này bạn cần phải ghi đè phương thức get của BaseDetailView, trông giống như:

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) 

Vì vậy, trong lớp học của bạn, bạn sẽ cần phải cung cấp một phương pháp get mới mà đã làm các kiểm tra URL giữa lấy đối tượng và thiết lập bối cảnh. Một cái gì đó như:

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) 

Khi bạn kết thúc quá nhiều chức năng, nó sẽ trở nên có vấn đề cho dù giá trị thực sự sử dụng chế độ xem chung cho điều này, nhưng bạn biết.

+1

Bạn chỉ có thể gọi cha mẹ nhận được phương thức trong trường hợp khác tại đây. Nó sẽ sạch hơn nhiều. Nó hoàn toàn đáng giá như các khung nhìn chung dựa trên lớp được mở rộng cho chức năng tùy chỉnh. – vimukthi

+1

Điều tốt về cách tiếp cận của bạn là chúng ta không cần phải lo lắng nếu việc thực hiện các thay đổi của BaseDetailView.get, nhưng nhược điểm là chúng ta cần phải thực hiện truy xuất đối tượng hai lần cho mọi yêu cầu, mà đối với tôi không phải là giá trị hiệu suất tiềm năng/khả năng mở rộng. – Rolo

+0

Để tránh nhấn đúp vào 'get_object', bạn có thể ghi đè lên nó trong lớp của riêng bạn hoặc mixin và lời nói đầu với một kiểm tra' if hasattr (self, 'object', None) '; nếu kiểm tra thành công, hãy trả lại 'self.object' nếu không gọi' get_object' của cha mẹ. Chính xác như @Raumkraut đã được triển khai (https://stackoverflow.com/a/12858110). – interDist

10

đang phát triển về câu trả lời và ý kiến ​​Rolo, tôi đã đưa ra quan điểm chung sau đây để phục vụ cho mục đích này:

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

này được sử dụng theo cách tương tự như DetailView bình thường, và nên làm việc cho bất kỳ mô hình mà thực hiện chính xác get_absolute_url.

Các vấn đề liên quan