Generic ViewSets — An Introduction
Glad to have you onboard! This is the starting line. An introduction to Generic ViewSets, their uses and how to customize them to fit your needs.
I believe the best place to start is to see where we need to end up. And we have a very simple aim... we need to build this:
For those of you who just went to their profile pages to see the article count, welcome back. For those who didn’t, please have a good look at the above image… we’re going to be staring at it quite a bit throughout this series.
Like I promised in the Prologue, here are a list of things you should be familiar with:
- Django Models — How to build them.
- Serializers — Model Serializers
- AbstractUser — And how to set them up. (I will go over this as well.)
- ModelViewSets — Are awesome.
Setting The Project Up
…The author then set the project up…
Here is the directory structure to make you feel a little comfortable…
We will be working primarily with the users_module
directory. You can find this project here.
Let’s start with the models. We will only consider the User model for now. Let’s deal with the articles themselves a little later.
An aside on the AbstractUser:Traditionally, if we wanted the User of our system to have more fields (in our case we have the bio, the headline etc). We would make a model, usually called `profile` and then have a one-to-one relation with the user model. However, the recommended way now is to use AbstractUser. AbstractUser is a way for you to extend your User model without completely overwriting the inbuilt Django User model. As you can see below, we inherit the AbstractUser and we don't need the `models.Model`. I have mentioned it in the comments below as well, that the first 5 fields do not need to be mentioned, they will be there even if we don't write them explicitly.For more information, I highly recommend this article by Vitor Freitas - Simple Is Better Than Complex: How To Extend The Django User Model
Here is the User model:
Now, there are a few things that should strike you as problematic:
- We would never store
articles
orfollowing
this way. They are both dynamic properties and should be calculated in the serializer, the view or by using a computed property (We will talk about this in a future series). - The
headline
is dynamic as well and should be calculated in a view. - The
bio
should have a max length.
We will fix these issues eventually, but they are actually going to force us to use the topics we discuss in this series.
Let’s talk about the views now. We will assume that we only want to retrieve information for now. Here is the way we would do it using ModelViewSet
:
The serializer is simple:
This is ugly. There is redundancy in the code, we are repeating ourselves multiple times, and I’m confident my editor thinks I’m stupid.
Many of you will very rightly point out that ModelViewSets were not meant for a single endpoint. They are meant to make it easier to build multiple endpoints that pertain to the same model. But scalability is something a developer should always keep in mind, your code should be future proof. In our case, we will be adding more endpoints in the future.
Here is the Generic ViewSet doing the same thing:
The only change you will notice is the ListModelMixin
. We have inherited a class ListModelMixin
in our original UserViewSet
.
A mixin
is basic python class inheritance
. When I include the ListModelMixin
, there is a piece of code that is included in the current class without me having to explicitly write it.
Here is the code if you wanna have a look:
This is the same list
endpoint that is auto created when you use ModelViewSet
.
So basically, you can now choose which endpoints you want and which ones are not relevant. Similar to this, there are:
CreateModelMixin
UpdateModelMixin
RetrieveModelMixin
DestroyModelMixin
Pro Tip: Your view won't work if the mixins are not the first to be inherited.
class UserViewSet(GenericViewSet, ListModelMixin)
--- Wrong
class UserViewSet(ListModelMixin, GenericViewSet)
--- Correct
We have not yet dealt with the get_queryset()
issue. The fact that we’re using a get_queryset
method that only returns a single User object. But that’s also a set-up for a future article.
Essentially,
Generic ViewSets are bare-bone versions of Model ViewSets. They don’t come with the out of the box implemented endpoints. They do however, come with the
get_queryset
and theget_serializer_class
methods.
Well, that’s it for this one. We set the project up and explored the basic difference between GenericViewSets and ModelViewSets. In the upcoming articles however, things get a little more interesting when we talk about custom endpoints.
I hope to see you soon…