Create easily a REST API with the django rest framework!
Hi! Are you near to create a new API, and you don’t know which framework to use? If this API will be added to a django project, the django rest framework will be perfect to create this API with few lines of code!
What’s a REST API?
The REST architecture will allow us to think first of an API describing the resources used in our django application. The main point of using a REST API is that we’ll have a separation between the client and the server. Then multiple clients can be developped consuming the ressources given by the API we made !
Another advantage of using a REST architecture is that we can easily request the API with simple HTTP request. GET requests will retrieve elements, POST requests will modify them, DELETE requests will delete them, etc… If you want to know more about the REST architecture I invite you to read this article.
For what?
Well, if you want to share your data that will be used by other platforms or if you want them to interact with other services. For example, what’s cool with all the APIs available is that you can make them interact together, all you need to do is to create the bridge between them. We can create a link between Trello and Twitter, we just need to trigger modifications in one of them and modify the other. Here, we’ll just create a simple read only API to retrieve all data available in this blog:
- Posts
- Categories
- Tags
The django rest framework
The django rest framework will allow us to create easily and with few lines of code, a REST API on top of our django application. So I recommend you this framework if you have an existing django project. If you’re starting from scratch, don’t worry, you just need to create a models.py which is not really long or complex :).
Prequel
For this little introduction, we’ll start with a little django project (this blog). As I said few lines before it’s that you need a models.py with few entities and you should be able to follow this introduction.
In my case, I have three ckasses in my models.py:
- Post
- Category
- Tag
If you want a little diagram, they look like that:
Installation
To install it, you’ll have two choices, install it with pip or from github. I’ll just show the first one because it’s the most common and the easiest one. It’s time to activate your virtualenv , let’s start!
|
|
Or you can add them in your requirements.txt.
Now, let’s create a new application to develop our API! Open a terminal, go to the root of your django project and write:
|
|
If everything went ok, you should have a new folder called api, containing a migrations folder, files like models.py, admin.py, views.py, etc… You can delete the models.py, admin.py, and the migrations folder.
Viewsets
Viewsets will act like views in django. They will allow us to request the databasefor a specific request. We can compare them of controllers in the MVC pattern.
In this viewsets, you’ll have methods like:
- get
- post
- list
- create
But what’s awesome, is that you have viewset for every taste! Generic, ModelViewSet, ReadOnlyModelViewSet, etc…
In my case, I’ll use only ReadOnlyModelViewSet to have a specific viewset for my model and limiting actions to read actions only. (It would be a shame if everyone could be able to post articles :/)
Let’s code for god’s sake!
In api/views.py
|
|
Serializers
Serializers will allow use to… suspens… serialize (yeah I know that’s weird) our models instancies to JSON and the opposite. We can compare them to forms in django.
We’ll add inside our serializer, fields that we’ll need. We could then write our serializer like that:
|
|
That’s what we could write if the ModelSerializer class did not exist! We’ll just need to specify which model we want to serialie and the django rest framework will take care to create the fields automatically. Pretty cool:
|
|
And the class is not more readable :) (In my case, I put off the fields argument to have all the attributes of the model).
Nested Serializers
For the case of this blog, we can see that a blog can be linked to multiple tags and to a category. And we could like to nest this category inside the post element in the JSON. To do so, we can add:
- Create a serializer for the nested model and add it inside the model serializer.
- Use a forgotten japanese secret
Let’s start with the first point:
Create a nested serializer that will be added in our PostSerializer!
|
|
|
|
What’s useful with a nested serializer is that you can add specific rules for the serialization of the object such as adding specific fields (some SerializerMethodField for example).
And the last (and second) method waited by all. The method that will revolutionize the world of API’s creation. I’m speking of the famous ‘depth’ attribute.
|
|
This class attribute will allow us to specifcy the depth of serialization of the entity we want. Here the 1 value will include the category (with all its fields) inside our posts.
WARNING
Be careful! Here, we speak about serializations only. Nested element may change your viewset to minimize the number of request in the database. For example if we keep the previous viewset with the last serializer, we’ll have 1 request to retrieve ‘N’ posts and ‘N’ requests to retrieve each category of each post. So I recommend you to read the doc about prefetch_related and select_related of django.
Example: In the previous example, we try to include categories in each post JSON. As I said before we’ll have N posts displayed but N + 1 requests done to the database. Why? To display our JSON, the django rest framework will do:
|
|
Well, not really, but that’s how it’s globally working. So django will execute a SQL request to retrieve the category element from the post when the obj = post.category line will be executed. To counter this problem, we’ll need to warn django to load the nested elements / foreign keys elements.
For that, let’s go to the api/views.py file.
|
|
So with that, we’ll have just one SQL request because django will take care to request the database with a JOIN on the category table.
Routers
Routers will make the urls creation super easy without writting them all!
We’ll just need to specify the viewset and the name that we attribute to this viewset and the django rest framework will take care of create the urls.
If we create a router like that in our api/urls.py:
|
|
Then we will have 2 urls created automatically.
- ‘^posts/$’ with the name ‘post-list’
- ‘^posts/{pk}$’ with name ‘post-detail’
So we’ll have a lighter urls.py than a usual django urls.py.
Bonus: Let’s add some doc to our API
To make client development easier for every developer, we need to document correctly our API.
For that, we’ll install swagger which an automatic generator of documentation. It will show which urls are available to request but also the type of return from the API.
For that, we’ll start to add django_rest_swagger to our requirements.txt or with pip, it’s as you want.
After that, we’ll add ‘rest_framework_swagger’ to our django application list in our settings.py.
To finish, we need to include swagger urls to our urls.py
|
|
Et voilà the result ! https://blog.juanwolf.fr/api/docs/
The End
It’s over for our little introduction of the django rest framework, I hope you liked it! If you want to go learn more about it, I invite you to go on the website of the framework which is really well documented! Sur ce, Codez bien !