'Django detailview get_queryset and get_object
I am using Django detailview. initially, I used the URL pattern
url(r'^todo/details/(?P<pk>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),
my view is
class todoDetailView(DetailView):
model = models.todo
It worked fine.
In the second case, my URL is
url(r'^todo/details/(?P<id>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),
this time, I modified my view to
class todoDetailView(DetailView):
model = models.todo
# context_object_name = 'todo_detail'
def get_object(self, **kwargs):
print(kwargs)
return models.todo.objects.get(id=self.kwargs['id'])
It worked fine, I modified the second case to
class todoDetailView(DetailView):
model = models.todo
# context_object_name = 'todo_detail'
def get_queryset(self):
return models.todo.objects.get(id=self.kwargs['id'])
then I get an error,
Generic detail view todoDetailView must be called with either an object pk or a slug.
I know that there is no proper slug or pk provided. So, initially I added get_object() (it worked) but get_queryset() is not working. What is the difference in their working ??
And also if a user is getting details only based on the slug, I read on StackOverflow that
this can be used
slug_field = 'param_name'
slug_url_kwarg = 'param_name'
link - Generic detail view ProfileView must be called with either an object pk or a slug
Can anyone explain me actual working of get_object() and get_queryset() (also get_slug_field() if possible)
Along with the terms slug_field and slug_url_kwarg
Thanks in advance
Solution 1:[1]
The default get_object for DetailView tries to fetch the object using pk or slug from the URL. The simplest thing for you to do is to use (?P<pk>[\d]+) in the URL pattern.
When you override get_object, you are replacing this default behaviour, so you don't get any errors.
When you override get_queryset, Django first runs your get_queryset method an fetches the queryset. It then tries to fetch the object from that queryset using pk or slug, and you get an error because you are not using either of them.
The slug_field and slug_url_kwarg parameters are both defined in the docs. The slug_fields is the name of the field in the model used to fetch the item, and slug_url_kwarg is the name of the parameter in the URL pattern. In your case, you are fetching the object using the primary key (pk/id), so you shouldn't use either of these options.
For your URL pattern with (?P<id>[\d]+), you could use pk_url_kwarg = 'id'. That would tell Django to fetch the object using id from the URL. However, it's much simpler to use your first URL pattern with (?P<pk>[\d]+), then you don't have to override any of the methods/attributes above.
Solution 2:[2]
get_object() majorly uses with the generic views which takes pk or id
like: DetailView, UpdateView, DeleteView
where get_queryset() uses with the ListView where we are expecting more objects
Also, get_object() or self.get_object() uses pk as default lookup field or can use slug Field
a little peek at get_object()
if queryset is None:
queryset = self.get_queryset()
# Next, try looking up by primary key.
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
if pk is not None:
queryset = queryset.filter(pk=pk)
# Next, try looking up by slug.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
Solution 3:[3]
I can't help you with what the error message explicitly means, but get_queryset is used in listviews by get multiple objects, while get_object is used to get a single object (ie DetailView).
If you have a pk you can use to get an object, you don't need to specify a slug field. Slug field are used to filter out objects when you don't have or can't show the primary key publicly. This gives a better explanation of a slug field.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Deepanshu Mehta |
| Solution 3 |
