Django overriding detail view get method
Asked Answered
G

3

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?

Grimbal answered 25/8, 2019 at 12:16 Comment(2)
You haven't explained what you want to do. Why are you overriding the get method? What are you doing in that method?Kelleykelli
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.Saturate
S
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)
Saturate answered 25/8, 2019 at 13:44 Comment(2)
Please take a look at my edit. I find most solutions on internet where get method is overriden. But this is not working for me.Grimbal
@asdfkjasdfjk: but that is usually for function-based views.Saturate
T
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.

Tolerable answered 25/8, 2019 at 13:32 Comment(0)
G
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)
Glossa answered 15/6, 2023 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.