5

This is my post detail view and it works perfectly.

class PostDetailView(DetailView):
    model = Post
    context_object_name = 'post'
    template_name = 'posts/detail.html'

    def get_queryset(self, *args, **kwargs):
        request = self.request
        pk = self.kwargs.get('pk')
        queryset = Post.objects.filter(pk=pk)
        return queryset

    def get_context_data(self, **kwargs):
        context = super(PostDetailView, self).get_context_data(**kwargs)
        content['comments'] = Comment.objects.all()

        return context

However, when I add get method to the view it does not work anymore.

def get(self, request, *args, **kwargs):
    # how to return here so that it works exactly like before

After adding get method get_queryset and get_context_data do not gets called automatically and the context is empty in the template. So what would be the get method so that it works exactly like before?

EDIT My target is to do something like this

if request.is_ajax():
    html = render_to_string('comments/detail.html')  # ajax reply with html data
    return HttpResponse(html)
 return render 'posts/detail.html'

So where do I put this code and still want to keep call all methods such as get_queryset and get_context_data to be called automatically?

asdfkjasdfjk
  • 3,784
  • 18
  • 64
  • 104
  • 1
    You haven't explained what you want to do. Why are you overriding the get method? What are you doing in that method? – Daniel Roseman Aug 25 '19 at 12:23
  • 1
    That makes perfect sense, since the `get(..)` is already implemented to trigger the `get_context_data`, etc. and render the template with that context, so by overriding it, you remove the boilerplate logic. – Willem Van Onsem Aug 25 '19 at 12:31

3 Answers3

6

The idea of views like a DetailView, ListView, etc. is that it implements the boilerplate logic for you. So it has defined a function def get(self, request, *args, **kwargs) that is used to render the logic. You can usually tweak a few things by specifying the model, queryset, etc. without reimplementing the entire view.

For a DetailView [Django-doc], the logic is implemented in the BaseDetailView you can inspect the source code [GitHub]:

class BaseDetailView(SingleObjectMixin, View):
    """A base view for displaying a single object."""
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
2

One general piece of advice I want to share: Before overriding any attribute, one must have deep knowledge of what is the significance of that attribute (callable or not callable). This advice applies to any language or framework. Suppose when someone overrides the get in Django, all the methods that are being called from get will not be invoked unless one invokes that from overridden get. So you should see the source of get and observe that methods are called from that.

Saiful Azad
  • 1,823
  • 3
  • 17
  • 27
1

I know this is a rather old thread, but the solution seems simple: you need to call the original get() method at the end of your overriding get() method by calling something like:

return super(PostDetailView, self).get(request, *args, **kwargs)
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Harold Holsappel
  • 149
  • 1
  • 10