Slides here.
So far we've covered about developing a CRUD Web Application using Django and we have used a traditional MVC approach on developing the TodoApp. Now we'll see how we can expose a REST API for our TodoApp.
To understand more about what REST is, you can check this stackoverflow thread.
Firstly we'll need to add a new package djangorestframework into our django application. As django by default isn't REST friendly for developing application we need to add this new package to make developing RESTful applications easier.
$ pip install djangorestframeworkAfter you've installed this, go and add rest_framework on the INSTALLED_APPS list in the settings.py file:
INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'todos'
]Since our REST API is going to be fully JSON based, we'll need to add serializer classes which will automatically handle the serialization/deserialization task for us.
So, go and create a new file serializers.py under our todos directory:
from rest_framework import serializers
from .models import Todo
class TodoSerializer(serializers.ModelSerializer):
''' Serializer to map the Todo model to JSON. '''
class Meta:
"""Meta class to map serializer's fields with the model fields."""
model = Todo
fields = ('id', 'title', 'description', 'completed', 'created_at', 'user')
read_only_fields = ('created_at', 'id')In the above code, we've just created a new serializer TodoSerializer for our Todo model class.
In RESTful API routes there are generally two kinds of endpoints: collection endpoints and resource endpoints.
The collection endpoints are those which would return a list of resources on GET and which would create a new resource on POST and other HTTP verbs like OPTIONS, HEAD etc are supported as always.
Our our TodoApp todos collection endpoint would look like this:
GET /api/todos
POST /api/todos
So, to handle these we'll create a new view TodoListView since it's a collection endpoint. Go to your views.py and add a new class TodoListView.
from rest_framework import generics
from todos.models import Todo
from todos.serializers import TodoSerializer
class TodoListView(generics.ListCreateAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializerNow this view will be responsible for creating a new todo item when it gets a POST request with payload and will return a list of todo items (in JSON) when it gets a GET request.
We'll still need to add a new url that points to this view, let's add this new url for /api/todos in our urls.py file:
from todos import views
urlpatterns = [
...
url(r'^api/todos$', views.TodoListView.as_view(), name='api_todo_list')
]Now that we have our todo list API ready, let's go and test it using Postman.
You can go and send a GET request on http://localhost:8000/api/todos and you should receive a list of todo items in JSON as a response.
And if you try a POST request on the same url http://localhost:8000/api/todos with a JSON payload of data you want to create, you'll see that it creates a new item.
With the above TodoListView we are able to add Create and Read of CRUD functionality in our TodoApp using REST API.
Now we also need to be able to Update, Delete and Read individual todo items to complete all the CRUD operations for the todolist.
To to this, we'll have to create a new API endpoint which we'll be a resouce endpoint unlike the collection endpoint we've created above.
For this we'll add a new view class in our view.py file, TodoItemView:
class TodoItemView(generics.RetrieveUpdateDestroyAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializerNow, this new view will be responsible for updating, retrieving and deleting individual todo items using the REST API.
Finally, we'll need to add a new url that would point to this new view when a resource endpoint is hit.
The endpoint will have to be something like /api/todos/:id that supports methods GET, PUT, PATCH and DELETE.
GET /api/todos/:id
PUT /api/todos/:id
PATCH /api/todos/:id
DELETE /api/todos/:id
This new endpoint will need to have id (Primary Key) as it needs to know which resource is going to be manipulated or retrieved.
For this endpoint we'll add the following urn patten in our urls.py file:
urlpatterns = [
...
url(r'^api/todos$', views.TodoListView.as_view(), name='api_todo_list'),
url(r'^api/todos/(?P<pk>[0-9]+)$', views.TodoItemView.as_view(), name='api_todo_item')
]Now that we have both list and item endpoints ready for the todolist, we have exposed the full CRUD functionalities of our application into REST Api endpoints.
Using Postman let's tryout this new endpoint /api/todos/:id.
Do a GET request on http://localhost:8000/api/todos/:id with any todo item id you have in your database and you should receive the data for that particular todo item.
A PATCH request on the same url http://localhost:8000/api/todos/:id with a JSON payload of data for any item id will update the data in the database according to the data sent in the payload.
A DELETE request on the same url http://localhost:8000/api/todos/:id will delete the item in the database given by the provided id.