Why queryset returns value instead of instance in Django Views?

My Problem

I have a queryset in Django View. That queryset should return an instance. But instead of that it returns a value

Models.py

class Author(models.Model):
    name = models.CharField(max_length=250, unique=True)
    
    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('authors:author_detail', args=[str(self.id)])


    class Meta:
        verbose_name = 'Author'
        verbose_name_plural = 'Authors'

Projects URLS.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('author/', include('authors_app.urls', namespace='authors')),
]

authors_app ULRS.py

from .views import *

app_name = 'authors'

urlpatterns = [
    path('<int:pk>/', AuthorDetail.as_view(), name='author_detail'),
]

Views.py

class AuthorDetail(ListView):
    model = Book
    context_object_name = 'author_books'
    template_name = 'author-detail.html'
    queryset = Book.objects.all().order_by('bookinfo__bestseller')
    paginate_by = 36

    def get_queryset(self, **kwargs):
        author_id = Author.objects.get(pk = self.kwargs['pk'])
        print(author_id)
        qs = super().get_queryset(**kwargs)
        return qs.filter(author = author_id)


    def get_context_data(self, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Add in a QuerySet 
        context['author'] = Author.objects.get(pk = self.kwargs['pk'])
        # context['image'] = f"/mnt/HDD/wiki/parser/images/photos/10.png"
        return context

Traceback

Traceback (most recent call last):
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/views/generic/list.py", line 142, in get
    self.object_list = self.get_queryset()
  File "/mnt/HDD/tibrains/08/titest_project/authors_app/views.py", line 17, in get_queryset
    return qs.filter(author = author_id)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/query.py", line 941, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1393, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1412, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1320, in build_filter
    self.check_related_objects(join_info.final_field, value, join_info.opts)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1147, in check_related_objects
    self.check_query_object_type(value, opts, field)
  File "/mnt/HDD/tibrains.test/titest-env/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1128, in check_query_object_type
    raise ValueError(
ValueError: Cannot query "Lawrence Gilman": Must be "Author" instance.

When I open authors page - mysite.com/author/51/ I've got an Error: Cannot query "Lawrence Gilman": Must be "Author" instance.

Question

How can I get an instance in that queryset?

I think this is the problem:

author_id = Author.objects.get(pk = self.kwargs['pk'])

use filter instead of get:

author_id = Author.objects.filter(pk = self.kwargs['pk'])

You can filter with the author_id itself, and thus obtain a get_queryset with:

from django.shortcuts import get_object_or_404


class AuthorDetailView(ListView):
    # …

    def get_queryset(self, **kwargs):
        return super().get_queryset(**kwargs).filter(author_id=self.kwargs['pk'])

    def get_context_data(self, **kwargs):
        return super().get_context_data(
            **kwargs, author=get_object_or_404(Author, pk=self.kwargs['pk'])
        )
Back to Top