Create a REST API With Django

I am going to use Python and the Django REST API framework to build a simple web service that will be able to provide data and functionality to many different platforms and applications. I will be building an invoicing API, with endpoints for viewing, creating and deleting invoices. All within 20 steps or less. I am assuming you already have Python installed on your PC/Mac. I am using Mac but the steps shouldn’t be any different for PCs.

STEP 1
Create a folder somewhere in your local machine
Example:
$mkdir LearningREST

STEP 2
Create a virtual environment
Example:
$cd LearningREST
$virtualenv env

STEP 3
Activate the virtual environment
Example:
$source env/bin/activate

STEP 4
Install django in your virtual environment
Example:
$pip install django

STEP 5
Install django restframework
Example:
$pip install djangorestframework

STEP 6
Create a django project
Example:
$django-admin.py startproject invoicesproject

STEP 7
Create an app within the project
Example:
$cd invoicesproject
$python manage.py startapp invoices

Open the settings.py under invoicesproject.
Go to “INSTALLED_APPS” section,
add ‘rest_framework’
add ‘invoices.apps.InvoicesConfig’

STEP 8
Run the web server now
Example:
$python manage.py runserver

Check the line that says “Starting development server at”
Assuming the http address says http://127.0.0.1:8000/
Open a browser and browse to http://127.0.0.1:8000/

The message in the browser should say “It worked!”

STEP 9
Create a model class.
To do so, open the models.py under invoices
Enter the following information

class Invoice(models.Model):
created = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=100)
description = models.TextField(blank=True, default=”)
total = models.DecimalField(max_digits=7, decimal_places=2)
paid = models.DecimalField(max_digits=7, decimal_places=2)

Save the file. Open your terminal or the command prompt.
Execute the following
$python manage.py makemigrations invoices
$python manage.py migrate

You can test the model now from a shell.
In your terminal or your command prompt, execute the following

$python manage.py shell
>>> from invoices.models import Invoice
>>> Invoice.objects.all()
>>> invoice = Invoice(name = ‘My First Invoice’, description = ‘A very detailed description’, total = 100.00, paid = 0.00)
>>> invoice.name
>>> invoice.total
>>> invoice.paid
>>> Invoice.objects.all()
>>> invoice.save()
>>> Invoice.objects.all()

STEP 10

We will create a serializer class.
To do so, go to your invoices folder and create a file called serializers.py

Type the following content in the serializers.py

from rest_framework import serializers
from invoices.models import Invoice

class InvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Invoice
fields = (‘name’, ‘description’, ‘total’, ‘paid’)

Now we’ll try this serializer class from the shell.
Open your terminal or your command prompt and type the following:
$python manage.py shell
>>> from invoices.models import Invoice
>>> from invoices.serializers import InvoiceSerializer
>>> Invoice.objects.all()
>>> invoice = Invoice.objects.get()
>>> invoice.name
>>> serializer = InvoiceSerializer(invoice)
>>> serializer.data

STEP 11
We will create a View of our application.
To do so, open the views.py file under invoices folder and remove all the contents.

Type the follow in the views.py

from rest_framework.decorators import api_view
from rest_framework.response import Response
from invoices.models import Invoice
from invoices.serializers import InvoiceSerializer

@api_view([‘GET’])
def invoice_list(request):
if request.method == ‘GET’:
invoices = Invoice.objects.all()
serializer = InvoiceSerializer(invoices, many=True)
return Response(serializer.data)

STEP 12
Create a urls.py file under the invoices folder.
Type the following content

from django.conf.urls import url
from invoices import views

urlpatterns = [
url(r’^invoices/$’, views.invoice_list),
]

Open urls.py under invoicesproject folder and update with the following content

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
url(r’^’, include(‘invoices.urls’)),
]

STEP 13
Go to your terminal or your command prompt and execute the following
$python manage.py runserver

Go to the url http://127.0.0.1:8000/invoices/

STEP 14
Let's add the capability to retrieve a single invoice.
To do so, open the serializers.py under the invoice folder and update with the following

from rest_framework import serializers
from invoices.models import Invoice

class InvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = Invoice
fields = (‘id’, ‘name’, ‘description’, ‘total’, ‘paid’)

Open the views.py file under the invoice folder and update with the following.
Add the following import

from rest_framework import status

Add the following method

@api_view([‘GET’])
def invoice_detail(response, pk):
try:
invoice = Invoice.objects.get(pk=pk)
except Invoice.DoesNotExist:
return Response(status = status.HTTP_404_NOT_FOUND)

if request.method == ‘GET’:
serializer = InvoiceSerializer(invoice)
return Response(serializer.data)

Open the urls.py under invoices and add the following:

url(r’^invoices/(?P[0-9]+)/$’, views.invoice_detail),

Execute this url http://127.0.0.1:8000/invoices/ in your browser.

Take the id number and append it to the url like the following

http://127.0.0.1:8000/invoices/1

In my case, the primary key for that record was 1

STEP 15
Let's add the capability to create a new invoice.
First, download postman to call your API from outside and post data to it. Download from here https://www.getpostman.com/

Open the views.py under the invoices folder and update the invoice_list function with the following

@api_view([‘GET’, ‘POST’])
def invoice_list(request):
if request.method == ‘GET’:
invoices = Invoice.objects.all()
serializer = InvoiceSerializer(invoices, many=True)
return Response(serializer.data)
elif request.method == ‘POST’:
serializer = InvoiceSerializer(data = request.data)

if serializer.is_valid():
serializer.save()
return Response(serializer.data, status = status.HTTP_201_CREATED)
return Response(serializer.errors, status = status.HTTP_400_NOT_FOUND)

Let’s restart our server to make sure all the changes took effect. Execute the following:

$python manage.py runserver

You can quickly check our invoice_list function with GET method is still working by browsing to

http://127.0.0.1:8000/invoices/

Now, let’s use postman to check this updated function fully.
Start postman, in the Builder tab (look at the top of this application to be sure. You should be there by default).

From dropdown where you see enter request URL, select POST and type the following
http://127.0.0.1:8000/invoices/

select Body right below it and select raw right below that. Select JSON from the body type. Enter the following in the body

{
“name”: “My newest Invoice”,
“description”: “Another description”,
“total”: 25.00,
“paid”: 25.00
}

Click Send and you should get a response back similar to the following.
The only difference between my example and yours could be the id value.

{
“id”: 2,
“name”: “My newest Invoice”,
“description”: “Another description”,
“total”: “25.00”,
“paid”: “25.00”
}

STEP 16

Let's add the update function in our API. To do so, open views.py.
Update the invoice_detail function with the following:

@api_view([‘GET’, ‘PUT’])
def invoice_detail(request, pk):
try:
invoice = Invoice.objects.get(pk=pk)
except Invoice.DoesNotExist:
return Response(status = status.HTTP_404_NOT_FOUND)

if request.method == ‘GET’:
serializer = InvoiceSerializer(invoice)
return Response(serializer.data)

elif request.method == ‘PUT’:
serializer = InvoiceSerializer(invoice, data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)

To test the new feature, open postman. Select PUT from GET or POST dropdown menu.
Type in the url http://127.0.0.1:8000/invoices/2/
We want to update the 2nd invoice
Select the body tab and check the raw body type. Make sure to select JSON as the message type.
Enter following content in the form body and click Send

{
“id”: 2,
“name”: “My awesome Invoice”,
“description”: “Another description”,
“total”: “2500.00”,
“paid”: “2500.00”
}

You should get a response back with your updated data.

STEP 17
Delete function is easier. Open views.py and update the invoice_detail function with the following content

@api_view([‘GET’, ‘PUT’, ‘DELETE’])
def invoice_detail(request, pk):
try:
invoice = Invoice.objects.get(pk=pk)
except Invoice.DoesNotExist:
return Response(status = status.HTTP_404_NOT_FOUND)

if request.method == ‘GET’:
serializer = InvoiceSerializer(invoice)
return Response(serializer.data)

elif request.method == ‘PUT’:
serializer = InvoiceSerializer(invoice, data = request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status = status.HTTP_400_BAD_REQUEST)

elif request.method == ‘DELETE’:
invoice.delete()
return Response(status = status.HTTP_204_NO_CONTENT)

To test our delete function, let’s open postman. Select DELETE from the dropdown of GET, POST or PUT.
Provide the URL http://127.0.0.1:8000/invoices/2/
You shouldn’t see anything in the response body. The status should say, 204 No Content.
You have just deleted the record id 2.

To validate the record got deleted, you select the GET http method dropdown and type in the URL http://127.0.0.1:8000/invoices/

You should see only the remaining record.

Create a REST API With Django

Leave a Reply

Your email address will not be published. Required fields are marked *