user3284589
user3284589

Reputation: 343

How can I get 'pk' or 'id' in `get_context_data` from CBV?

How can I get 'pk' or 'id' in get_context_data from CBV DetailView?

class MyDetail(DetailView):
    model = Book
    template_name = 'book.html'
    
    def get_context_data(self, **kwargs):
            context = super(MyDetail, self).get_context_data(**kwargs)
            context['something'] = Book.objects.filter(pk=pk)
            return context

url:

url(r'^book/(?P<pk>\d+)/$', MyDetail.as_view(), name='book'),

Upvotes: 34

Views: 43150

Answers (7)

tangowithdjango
tangowithdjango

Reputation: 11

def get_context_data(self, request, pk, *args, **kwargs):
    context = super(MyDetail, self).get_context_data(**kwargs)
    context['something'] =Book.objects.filter(pk=self.kwargs.get('pk'))
    return context

Filter returns a query set that matches the lookup parameter (pk). Since 'pk' is unique, it would return the same results as get but for performance issues, ideally you'd want to use the get method to return one single object:

def get_context_data(self, request, pk, *args, **kwargs):
    context = super(MyDetail, self).get_context_data(**kwargs)
    context['something'] =Book.objects.get(pk=self.kwargs.get('pk'))
    return context

Upvotes: 1

C.K.
C.K.

Reputation: 5498

self.kwargs['pk'] it doesn't work in Django 2.2

in DetailView

self.object is the object that this view is displaying.

So, to access the object's fields like id or pk just self.object.id or self.object.pk

So, The answer in Django 2.2 can be like:

class MyDetail(DetailView):
    model = Book
    template_name = 'book.html'

    def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['something'] = Book.objects.filter(pk=self.object.pk)    # <<<---
            return context

Django 2.2 Doc

Upvotes: 7

Milad shiri
Milad shiri

Reputation: 990

you can simply get it in the 'get' method, like this:

def get_context_data(self, request, pk, *args, **kwargs):
    context = super(MyDetail, self).get_context_data(**kwargs)
    context['something'] =Book.objects.filter(pk=self.kwargs.get('pk'))
    return context

Upvotes: 3

raghu
raghu

Reputation: 394

class MyDetail(DetailView):
    model = Book
    template_name = 'book.html'

    def get_context_data(self, **kwargs):
            context = super(MyDetail, self).get_context_data(**kwargs)
            context['something'] =Book.objects.filter(pk=self.kwargs.get('pk'))
            return context

Upvotes: 8

Berislav Lopac
Berislav Lopac

Reputation: 17243

In addition to getting it from self.kwargs as Daniel Roseman suggested, you can use self.get_object().pk, for example if you change your URL identifier from pk to, say, slug or something.

Upvotes: 3

waverider
waverider

Reputation: 318

In get_context_data you already have the object in self.object (and you can do self.object.pk). Here's what happens upstream in the class hierarchy (DetailView inherits from BaseDetailView):

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)

Reading Django source code to understand stuff is incredibly easy.

And by the way, I am not sure you can always rely on the fact that kwargs has a 'pk' key.

Upvotes: 5

Daniel Roseman
Daniel Roseman

Reputation: 599450

You can get it from self.kwargs['pk'].

I'm not sure why you want to, though, since the superclass already gets the Book corresponding to that pk - that's the whole point of a DetailView.

Upvotes: 64

Related Questions