Redirect from Generic View DetailView in Django

前端 未结 2 1082
渐次进展
渐次进展 2020-12-31 04:41

I\'m using Django\'s class based DetailView generic view to look up an object for display. Under certain circumstances, rather than displaying the object, I wish to back ou

相关标签:
2条回答
  • 2020-12-31 05:10

    This isn't a natural fit for DetailView. To do this you need to override the get method of BaseDetailView, which looks like:

    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)
    

    So in your class you'd need to provide a new get method which did the URL check between fetching the object and setting up the context. Something like:

    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)
    

    As you end up overriding so much of the functionality it becomes questionable whether it's worth actually using a generic view for this, but youknow.

    0 讨论(0)
  • 2020-12-31 05:14

    Developing on Rolo's answer and comments, I came up with the following generic view to serve this purpose:

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

    This is used in the same manner as the normal DetailView, and should work for any model which implements get_absolute_url correctly.

    0 讨论(0)
提交回复
热议问题