SIMPLE REST API WITH DJANGO REST FRAMEWORK.
Habib Audu
Posted on February 7, 2020
Hi guys! In this post am going to be taking us on how to build a simple rest Api with Django rest framework, performing all CRUD (create, read, update, delete) operations. Django rest framework is a robust toolkit for building web APIs.
A RESTful API is an application programming interface (API) that uses HTTP requests to create, Read, update and delete data.It defines a set of functions which developers can perform requests and receive responses via HTTP protocol.
GETTING STARTED
First thing first lets setup a new Django project.
install pipenv if you don't already have it
$ pip3 install pipenv
Create a virtual environment or activate one
$ pipenv shell
Install Django
$ pipenv install django
Create a Django project
$ django-admin startproject simple_app
Create a Django app
$ django-admin startapp rest_api
RUN THE APPLICATION
(simple_app) $ python manage.py runserver
The application is running at http://127.0.0.1:8000/
Setup Django REST Framework
(simple_app) $ pipenv install djangorestframework
Now lets add our Django app rest_api
and restframework
to INSTALLED_APPS list
simple-app/settings.py
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_api.apps.RestApiConfig', # Add this line
'rest_framework', # Add this line
]
We will be creating a sample customer API
, where we can perform the various CRUD operations
. Open our models file and add the following lines.
Model
rest_api/models.py
from django.db import models
from rest_api.helpers import LENGTH_OF_ID, generate_id
class Customer(models.Model):
id = models.CharField(
max_length=LENGTH_OF_ID, primary_key=True,
default=generate_id,
editable=False
)
name = models.CharField(max_length=100, null=False)
product = models.CharField(max_length=100, null=False)
is_active = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
Add a new file called helpers.py
in our app folder
rest_api/helpers.py
import uuid
from django.utils.http import int_to_base36
LENGTH_OF_ID = 12
def generate_id() -> str:
"""Generates random string with length of `ID_LENGTH`"""
return int_to_base36(uuid.uuid4().int)[:LENGTH_OF_ID]
helpers.py helps us generate unique ids of length 12
Now run this two commands on the terminal
(simple_app) $ python manage.py makemigrations
(simple_app) $ python manage.py migrate
Makemigrations
is responsible for packaging up your model changes into individual migration files, so anytime a change is made on your models.py you need to run python manage.py makemigrations
. Migrate
is responsible for applying those changes to your database, you should also run python manage.py migrate
every time you generate a new migration file.
Serialize The Customer Model
Add a new file called serializer.py
in our app folder
rest_api/serializer.py
from rest_framework import serializers
from rest_api.models import Customer
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = ["id", "name",
"product","is_active","created_at","updated_at"]
A serializer converts data stored in the database and data you define in the models into a format which is more easily communicated via an API.
Now django models represent data stored in your database, but an API will need to transmit information in a less complex structure.
so the serializer convert your data into JSON so it can be transmitted over an API.
ViewSet
serializers translate information in both directions
reads and writes, views defines the functions
read, create, update, deletewhich will be available via the API. It has the following built-in operations.
create(): To Create an instance.
retrieve(): Retrieve/Read an instance.
update() : Update all fields of an instance.
partial_update(): Update selected fields of an instance.
destroy(): Deletes an instance.
list(): Retrieve/Read an instance.
To CREATE
a customer
lets populate our view open views.py
in our app folder.
rest_api/views.py
from rest_framework import viewsets
from rest_framework.status import (
HTTP_201_CREATED,
HTTP_200_OK,
HTTP_400_BAD_REQUEST,
HTTP_404_NOT_FOUND,
HTTP_204_NO_CONTENT
)
from rest_framework.response import Response
from rest_api.models import Customer
from rest_api.serializer import CustomerSerializer
class CustomerViewSet(viewsets.ViewSet):
'''ViewSet to add a customer'''
serializer_class = CustomerSerializer
def create(self, request):
serializer = self.serializer_class(data=request.data)
if not serializer.is_valid():
return Response(status=HTTP_400_BAD_REQUEST)
serializer.save()
return Response(data=serializer.data,
status=HTTP_201_CREATED)
we have imported some modules here, `viewsets` from rest_framework, which is going to serve as the `superclass` to our `CusterViewSets`,various status code from rest_framework to send appropriate status_code with our response,`Response` which actually sends the response, Customer model from models.py and our CustomerSerializer. Inside create(), we send the request data into the serializer for serialization, we call `is_valid()` to check the validity of our data, save() if its valid and return the serialized data with a status code of 200.
To GET
all customers
lets populate our view open views.py
in our app folder, inside CustomerViewSet
just after the create method
add the following lines
rest_api/views.py
def list(self, request):
queryset = Customer.objects.filter(is_active=True)
serializer = CustomerSerializer(queryset, many=True)
return Response(data=serializer.data,status=HTTP_200_OK)
Here we query our Customer table/model for all instances of customer where the value of `is_active` is `True` and pass the resulting `queryset` into our CustomerSerializer for serialization, then return the serialized data and a status code of 200.
To DELETE
a customer
lets populate our view open views.py
in our app folder, inside CustomerViewSet
just after the list()
method add the following lines
rest_api/views.py
def destroy(self, request, pk):
try:
customer_detail = Customer.objects.get(pk=pk, is_active=True)
except Customer.DoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
customer_detail.is_active = False
customer_detail.save()
return Response(status=HTTP_204_NO_CONTENT)
Here we try to get an instance of customer which has `pk` that was passed and has is_active as True, if thats is successful we change `is_active` to `False`, save() and return status of 204.
To PATCH
a customer
lets populate our view open views.py
in our app folder, inside CustomerViewSet
just after the destroy()
method add the following lines of code.
rest_api/views.py
def partial_update(self, request, pk):
customer = Customer.objects.filter(pk=pk).first()
if not customer:
return Response(status=HTTP_404_NOT_FOUND)
serializer = self.serializer_class(
customer, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(data=serializer.data, status=HTTP_200_OK)
Here we try to get an instance of customer with the `primary_key` that was passed `(pk)`, if thats is successful we pass the customer instance and request data into our serializer, if our serializer is valid we save() and return a response with serialized data and appropriate status code.
Next open serializer.py
inside class CustomerSerializer
just after class Meta
add the following lines
rest_api/serializer.py
def update(self, instance, validated_data):
instance.name = validated_data.get("name",instance.name)
instance.product = validated_data.get("product",instance.product)
instance.save()
return instance
To update we call the update() method inside the serializer class, it takes an instance of the object to update and validated data from the serializer. It update the instance save and return the instance to the view.
Now lets map to url, create another file in our django app url.py
rest_api/url.py
from django.urls import path, include
from django.conf.urls import url
from rest_api.views import (CustomerViewSet)
from rest_framework.routers import DefaultRouter
router = DefaultRouter(trailing_slash=False)
router.register(r'customer', CustomerViewSet, basename='customer')
urlpatterns = [
url(r'', include(router.urls)),
]
Now register this url in our project urls, Open simple_api/urls.py
, you can if you like remove all uncommented code there and add the following lines
from django.urls import path, include
urlpatterns = [
path("api/v1/", include("rest_api.url")),
]
This just includes the url we created in our rest_api.url.py
file
Start server
(simple_app) $ python manage.py runserver
Fire up postman. url http://127.0.0.1:8000/api/v1/customer
Feel free to run GET,DELETE and PATCH.
Conclusion
I don't think you can go wrong with django restframework wink.
Thanks for Reading cheers...
Posted on February 7, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2024