Louis Glenn
Louis Glenn

Reputation: 25

Why do I get a Key Error for 'post' in PostListView

I don't know why I got a Key Error message (KeyError at / 'post') when I def get_context_data in PostListView. But that was totally fine when I just def get_context_data in PostListDetailView.

Views.py

def home(request):
    post = get_object_or_404(Post, id=request.POST.get('post_id'))
    if post.likes.filter(id=request.user.id).exists():
        is_liked = True
    context = {
        'posts': Post.objects.all(),
        'is_liked': is_liked,
        'total_likes': post.total_likes(),
    }
    return render(request, 'blog/home.html', context)


def like_post(request):   # post like
    post = get_object_or_404(Post, id=request.POST.get('post_id'))
    is_liked = False
    if post.likes.filter(id=request.user.id).exists():
        post.likes.remove(request.user)
        is_liked = False
    else:
        post.likes.add(request.user)
        is_liked = True

    return HttpResponseRedirect('http://127.0.0.1:8000/')


class PostListView(ListView):
    model = Post
    template_name = 'blog/home.html'  # <app>/<model>_<viewtype>.html
    context_object_name = 'posts'
    ordering = ['-date_posted']
    paginate_by = 5
    is_liked = False

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        post = context['post']
        if post.likes.filter(id=self.request.user.id).exists():
            context['is_liked'] = True
        return context


class UserPostListView(ListView):
    model = Post
    template_name = 'blog/user_posts.html'  # <app>/<model>_<viewtype>.html
    context_object_name = 'posts'
    paginate_by = 5

    def get_queryset(self):
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        return Post.objects.filter(author=user).order_by('-date_posted')


class PostDetailView(DetailView):
    model = Post
    is_liked = False

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        post = context['post']
        if post.likes.filter(id=self.request.user.id).exists():
            context['is_liked'] = True
        return context

Below is the full traceback:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/

Django Version: 3.0.4
Python Version: 3.8.2
Installed Applications:
['blog.apps.BlogConfig',
 'users.apps.UsersConfig',
 'crispy_forms',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/Users/louisglenn/PycharmProjects/Pblog/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/Users/louisglenn/PycharmProjects/Pblog/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/louisglenn/PycharmProjects/Pblog/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/louisglenn/PycharmProjects/Pblog/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/louisglenn/PycharmProjects/Pblog/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File "/Users/louisglenn/PycharmProjects/Pblog/venv/lib/python3.8/site-packages/django/views/generic/list.py", line 157, in get
    context = self.get_context_data()
  File "/Users/louisglenn/PycharmProjects/Pblog/blog/views.py", line 50, in get_context_data
    post = context['post']

Exception Type: KeyError at /
Exception Value: 'post'

But when I changed my key to 'object_list', There is a new error 'AttributeError at / 'QuerySet' object has no attribute 'likes'

__class__   
<class 'blog.views.PostListView'>
context 
{'is_paginated': True,
 'object_list': <QuerySet [<Post: aasd>, <Post: asd>, <Post: ads>, <Post: asd>, <Post: asd>]>,
 'page_obj': <Page 1 of 3>,
 'paginator': <django.core.paginator.Paginator object at 0x102f6f640>,
 'posts': <QuerySet [<Post: aasd>, <Post: asd>, <Post: ads>, <Post: asd>, <Post: asd>]>,
 'view': <blog.views.PostListView object at 0x102f6f940>}
kwargs  
{}
post    
<QuerySet [<Post: aasd>, <Post: asd>, <Post: ads>, <Post: asd>, <Post: asd>]>
self    
<blog.views.PostListView object at 0x102f6f940>

Upvotes: 1

Views: 832

Answers (1)

Chase
Chase

Reputation: 5615

Looks like your context data doesn't have the key post, so this doesn't work

post = context['post']

Keep in mind that DetailView's get_context_data (the one being used in PostDetailView) might not be the exact same as ListView's get_context_data (the one being used in PostListView)

This line in PostDetailView and PostListView do not do the same thing-

context = super().get_context_data(**kwargs)

Since super refers to different classes for these 2. In case of PostDetailView, it's DetailView and in case of PostListView, it's ListView - hence context will not be the same across both functions.

You should check the context variable in each of those 2 different get_context_data using debugging, and find out which key you actually want.

Edit: To elaborate on how to debug, in case you're using VSCode, here's a quick guide on how to get started.

If you're on Pycharm, here's another quick guide on that!

After you start the debugging sense, you'll be able to setup breakpoints (by clicking next to the line numbers) and your code will pause in this breakpoints. You can then simply use the panels on the left (on VSCode) or bottom (on Pycharm) to view each variable value.

Upvotes: 1

Related Questions