Search code examples
pythondjangolistviewdjango-querysetdjango-related-manager

'Keyerror at /' when passing user with primary key in queryset for a listview


models.py

class Notes(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()
    date_added = models.DateTimeField(default=timezone.now)

views.py

class HomepageView(ListView):
    model = Notes
    template_name = "home.html"

    def get_queryset(self):
        return Notes.objects.filter(Q(author=self.kwargs['pk']))

It points out pk has KeyError, is there any way to get rid of it Thanks in advance...!


Solution

  • The self.kwargs contains the parameters, that are in the URL path. So in your urls.py, you should define shomething like:

    # urls.py
    
    from app.views import HomePageView
    
    urlpatterns = [
        path('<int:pk>/', HomePageView.as_view()),
    ]

    Then you can visit the page, with a valid primary key, so for example /14 if 14 is a valid primary key for a User.

    If you want to use the logged in user instead, you should use self.request.user instead:

    # in case you want to use the logged in user
    
    django.views.generic.list import ListView
    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class HomepageView(LoginRequired, ListView):
        model = Notes
        template_name = 'home.html'
    
        def get_queryset(self):
            return Notes.objects.filter(author=self.request.user)

    Note: it might be better to use get_user_model [Django-doc] to point to the user model, since if you later change the user model, altering the foreign keys will be easier.

     

    Note: You might want to consider using a DateTimeField(auto_now_add=True) instead of the models.DateTimeField(default=timezone.now), since that will make the field non-editable, etc.