Вопрос

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'),
Это было полезно?

Решение

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.

Другие советы

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

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

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.

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.

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
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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top