I want to get pk, or id of each post in 'views.py' so that I can use it for filtering and getting extra data in 'get_context_data'(Eventually, I want to check access of currently logged in user to each post). When website runs, it shows error message "KeyError at /post".
What could be a problem in this?
I was trying to apply example in django's official website(https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/).
I couldn't see a significant difference between this example and mine.
class PostList(ListView):
model = Post
template_name = 'post/post_list.html'
def get_queryset(self):
self.post = get_object_or_404(Post, pk=self.kwargs['pk'])
return Post.objects.filter(pk=self.post)
def get_context_data(self, **kwargs):
context = super(PostList, self).get_context_data(**kwargs)
context['post_info'] = self.post
context['check_access'] = Access.objects.filter(sender
return context
urlpatterns = [
path('<int:pk>', PostList.as_view(), name='post_list'),
]
I expected to see pk or id of each post but it shows below instead:
self.post = get_object_or_404(Post, pk=self.kwargs['pk']) ...
▼ Local vars
Variable Value
args
()
kwargs
{}
self
<post.views.PostList object at 0x107ab0ba8>
Well the URL is missing the primary key. You have to include it, like:
urlpatterns = [
path('<int:pk>', PostList.as_view(), name='post_list'),
]
Then you can query this with:
localhost:8000/post/123
with 123
the primary key for which you want to retrieve data.
This however does not look like a ListView
[Django-doc]. A ListView
should be used when you render a list of objects. This looks more like a DetailView
[Django-doc].
The nice thing about a DetailView
is that it even automatically filters on primary key and slug. It will automatically raise a 404 response if no such object exists.
So you likely want to use:
class PostDetailView(DetailView):
model = Post
context_object_name = 'post'
template_name = 'post/post_list.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['check_access'] = Access.objects.filter(...)
return context
The context_object_name
[Django-doc] specifies the name of the template variable for that object.