The DRF helps you make a simple API that exposes an endpoint for listings of an object and the details for a specific object.
My viewset looks like this:
class UserViewSet(ModelViewSet):
serializer_class = someSerializer
queryset = User.objects.all()
def get_queryset(self):
if self.request.user.has_perm('some.custom_permission'):
return (
super()
.get_queryset()
.filter(<some_custom_filtering>)
)
return super().get_queryset().filter(id=self.request.user.id)
Say my API is accessible from '<some_domain>/api/' (after registering my router appropriately). To get a listing of all my users I will call
<some_domain>/api/users/
And for a specific user (Michael Jordan)
<some_domain>/api/users/23
Both endpoints work as expected.
Just wondering why the call to retrieve a particular user still ends up going through the get_queryset() function.
Internally, the ModelViewSet
class inherits functionality from the mixins.RetrieveModelMixin
and the mixins.ListModelMixin
. And if one goes even deeper, at least in djangorestframework==3.12.4
, the RetrieveModelMixin
gets a specific object, serializes it and returns the serialized data. While the ListModelMixin
, calls the get_queryset()
function.
I know that overriding the get_object() function in my UserViewSet
view will make sure my retrieve object calls end up there (calling get_object
instead of get_queryset()
, but in its absence I don't get how or why the get_queryset()
function is involved.
Queryset is the way to bind view to a specific model.
You can create entire api with retrieve, list, update, create and delete actions simply by extending a few mixins and specifying queryset and serializer class, without actual method implementation.
Whatever you do, it eventualy ends up as ModelClass.objects.some_method
.
As @Brian said, get_object
also uses get_queryset
, and also filter_queryset
so retrieve/delete will raise 404 if you use filter and object does not pass it even if it actually exists.