Django REST Framework for Beginners: How to Create Your First API
Tags: webdev, django, api, python
Published: 2024-01-16 07:37:36

As a developer, beginner or seasoned, I am sure you have come across the word api or REST api before. So what does it mean? API stands for Applicatin Programming Interface and is a set of rules and instructions that allow different software components to communicate with one another. APIs make it easier of developers to create services and applications by using existing features or data from other platforms or applications. For example you can create a weather app by using data from weather forecasting companies, saving time from having to gather the data yourself.

REST API or RESTful API is an API that follows a set architectural contstraints for creating web services. REST APIs use HTTP requests to perform standard database functions such as creating, reading, updating and deleting. For more details, I suggest reading this [article](https://restfulapi.net/) .
Now that we have some understanding on APIs, let's build a simple API using django REST framework.

Django REST framework is a popular and powerful library for creating web APIs in Python. It provides a range of features and tools that make it easy to build, test, and document RESTful services. In this article, we will learn how to use Django REST framework to create a simple API with CRUD functionality. We will cover the following topics:

- How to install Django REST framework
- How to create models, serializers, and views.
- How to use URL patterns to define our API endpoints
- How to test our API

By the end of this article, you will have some understanding of how to use the Django REST framework to build your own web APIs. Let’s get started!

**Setup**

As we are using python and django, ensure you have django installed on your system. Install the django rest framework by running the command ‘pip install djangorestframework’. Add the django rest framework into your installed apps list in your setting.py file. Create a new django app which will be used to build the api and add it to the installed apps list. For the sake of this project, name the new app api.

```
INSTALLED_APPS = [
    ...
    'rest_framework',
    'api',
]
```

**Serializers and models**

Serializers are a very important part of Django REST framework , they handle convertion between complex data types such as model instances and primitive values such as JSON or other content types. They are also responsible for deserialization and check the input data for errors and convert it back to complex types.
To create serializers, start by creating a new file called ‘serializers.py’ inside the api app folder. Before you start working with serializers, ensure you create your models and make necessary migrations. Here is the model used for this project

```
from django.db import models
import uuid
# Create your models here.
class Posts(models.Model):
    id = models.UUIDField(primary_key=True,default=uuid.uuid4,editable=False,unique = True)
    post_name = models.CharField(max_length = 150,blank=False,null=True)
    post_user = models.CharField(max_length=50,blank=False,null=True)
    created = models.DateTimeField(auto_now_add=True,blank=False,null=True)


    def __str__(self):
        return self.post_user
```
You can choose to use custom id like in the case above, if not, you can skip that line of code entirely. If all this is new to you I suggest reading about [django](https://docs.djangoproject.com/en/5.0/)

Now in the serializers.py file, import the serializers module from rest_framework and all the models you want to work with. 



```
from rest_framework import serializers
from .models import Posts
```
Now create a new serializer class as shown below:

```
class PostsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Posts
        fields ='__all__'
```

- `PostsSerializers` is the name of of the serializer class. 
- `model=Posts` tells the class what model it will serialize.
- `fields='__all__'` tells the serializer which fields of the model will be serialized.

If you want to serialize more that one model, ensure you create a serializer class for each model.

**Views and urls**

Inside your main project folder, open the urls.py file and include the urls for the api app. 

```
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/',include('api.urls')),
]
```
Inside your api app folder create a urls.py file and add url patterns. You can add just one path for testing purposes.

```
from . import views
from django.urls import path

urlpatterns = [
    path('',views.index,name='index'),
]
```
Within the api app folder, open the views.py file. This is where the api logic will be written on. There are several imports needed: 

```
from .models import Posts
from .serializers import PostsSerializer
from rest_framework.decorators import api_view
from rest_framework.response import Response
```

- `from .models import Posts` : imports the model Posts created in the models.py file

- `from .serializers import PostsSerializer` : imports the PostsSerializer created in the serializers.py file. It will be used to convert instances of the model Posts into a format that can be easily rendered in JSON format.

- `from rest_framework.decorators import api_view` : imports the api_view decorator from the django rest framework. This decorator is used to define views for handling different HTTP requests such as GET , POST and others.

- `from rest_framework.response import Response` : imports the response class which is used to create HTTP responses in views.

Now create a view for the api:

```
@api_view(['GET'])
def index(request):
   urls = {
        'All Posts':'posts',
        'View single post':'post/<uuid:id>',
        'Create post':'create-post',
        'Delete post':'delete-post/<uuid:id>',
        'Edit post':'edit-post/<uuid:id>',
    }
    return Response(urls)
```
There are 2 main differences between this view and ordinary django view which are @api_view(['GET']) and the return Response(urls).

- `@api_view(['GET'])` : This decorator specifies the index view to only respond to HTTP GET requests

- `Response(urls)` : Creates a HTTP response with a JSON payload of the data urls.

Test the api by running the server and navigating to `http://127.0.0.1:8000/api/`. If done correctly you should see the following page

![API view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dvgu3hb0e7e9m9ey739a.png)

Congrats! You have an api up and running! Now let's add CRUD functionality to the api. CRUD stands for create, read, update, delete.

Before that, we want the api to be able to list all data in the model Posts, for that do the following:

```
@api_view(['GET'])
def listPosts(request):
    posts = Posts.objects.all()
    list = PostsSerializer(posts,many=True)
    return Response(list.data)
```

- `@api_view(['GET'])`: this decorator specifies the view listPosts will only accept HTTP GET requests

- `posts = Posts.objects.all()`: Retrieves all posts from the database

- `list = PostsSerializer(posts,many=True)`: Creates an instance of the PostsSerializer class, which is responsible for converting multiple instances of posts( all data retrieved from the model Posts). 

- `return Response(list.data)`: Generates a HTTP response using the Response class from django rest framework. The serializer.data contains the serialized data of the model. This response is in JSON format which is common in most APIs.

Create a url path in the urls.py file inside the api app folder. 

```
path('posts/',views.listPosts,name='posts'),
```
Then navigate to `http://127.0.0.1:8000/api/posts` and you should see the following page.

![Posts list image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nipbffj5g4zkfzuu0h0m.png)

You can add some data through the django admin panel, which will display on this page.

**CRUD Functionality**

**_Create_**

For the API to accept data input, there are a few changes that need to be made

```
@api_view(['POST'])
def makePost(request):
    serializer = PostsSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()

    return Response(serializer.data)

```

- `@api_view(['POST']` : This decorator specifies the view makePost should only accept HTTP Post requests.

- `serializer = PostsSerializer(data=request.data)` : Creates an instance of the PostsSerializer class. The serializer converts the request data into a Python dictionary that can be used to create or update a Post model instance.

- `if serializer.is_valid():serializer.save()` : This checks whether the data provided in the request is valid according to the rules defined in the serializer. If the data is valid, this line saves the data to the database using the serializer.

- `return Response(serializer.data)` : returns a Response object that contains the serializer’s data as the body.

Create a new url path in your urls.py file inside your api app folder.
`path('create-post/',views.makePost,name='create-post'),`

Navigate to this url and you should see something similar to this

![Create post view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lcvfvj03j7vzvhha9yin.png)

You can add data on content input. The data you add should be in  JSON format, for example
`{
        "id": "04c62826-14ee-489c-ba5e-56dc98d8d2a7",
        "post_name": "Home is 127.0.0.1",
        "post_user": "X53Tq0Ui",
        "created": "2024-01-11T11:55:41.126952+03:00"
    }`
Change the properties which are, id, post_name to match the fields your model has. Once complete, submit the form.

![Create post view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kr6vtoviarwimc932v6v.png)

After submitting the data, you should see the following:

![Post submit view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m2iy8r4zzno0w12tj3vv.png)

Also on the posts list you should be able to see it


![Post list view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4s7zr6f9rjwmyfqzrhv.png)

**_Read_**

Reading is simply viewing a specific post. It is done by passing the id of the post you want to view and it will be retrieved and a response will be rendered.

```
@api_view(['GET'])
def postDetails(request,id):
    post = Posts.objects.get(id=id)
    serializer = PostsSerializer(post,many=False)
    return Response(serializer.data)
```

- `@api_view(['GET'])` : This decorator specifies the view makePost should only accept HTTP Post requests.

- `post = Posts.objects.get(id=id)` : Retrieves a specific post from the database.

- `serializer=PostsSerializer(post,many=False)` : Creates a serializer instance for a single instance of the Posts model.

- `return Response(serializer.data)` : Returns a Response object that contains the serializer’s data as the body.

Create url path for this view inside the urls.py file in the api app folder `path('post/<uuid:id>/',views.postDetails,name='post'),`, then navigate to the link `http://127.0.0.1:8000/api/post/(add the id here without brackets)`. You should see the following


![single post view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8fuwalg9k6rivwbtrsrk.png) 

**_Update_**

For update, you pass in the id of the object that you want to update. The api will respond with the object which can be edited as needed and submitted. Let's do it practically.

```
@api_view(['POST'])
def editPost(request,id):
    post = Posts.objects.get(id=id)
    serializer = PostsSerializer(instance=post,data=request.data)
    if serializer.is_valid():
        serializer.save()

    return Response(serializer.data)
```

- `post = Posts.objects.get(id=id)` : Retrieves the specific object from the database.

- `serializer = PostsSerializer(instance=post,data=request.data)` : This is using the PostsSerializer to update the existing post with the new data prodived from request.data.

The rest of the code checks whether the data is valid and returns a JSON response of the new data.

Create another url route in the urls.py file inside the api app folder. 
` path('edit-post/<uuid:id>/',views.editPost,name='edit-post'),`

To test it, copy the id of an object you want to update and paste it to the url, example `http://127.0.0.1:8000/api/edit-post/c34fcfe4-dc69-4080-ace3-bcc0c02b79ef/`. It should open a new page similar to create post page where you can input a JSON data. Once you submit, it will replace the existing data with the new data. 

![Update page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7f2fp0iqgmb8twvl48n.png)



![Updated object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8oo5e3dsiiu13njx4qa9.png)


 
![Updated object on list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uc8xfl4g8mbu6a3d14u.png)

**_Delete_**

Just like read and update, pass the id of the object to the api view through the url, then the object will be retrieved from the database then finally it will be deleted. The HTTP request used in this case is DELETE. Let's see it in action

```
@api_view(['DELETE'])
def deletePost(request,id):
    post = Posts.objects.get(id=id)
    post.delete()
    return Response('Post Deleted!')
```
 

- `@api_view(['DELETE'])` : This decorator specifies that the deletePost view should only respond to HTTP DELETE requests.

- ` post = Posts.objects.get(id=id)` : Retrieves the Post instance with the given id from the database.

- `post.delete()` :  If the Post instance is found, it is deleted from the database using the delete() method.

- `return Response('Post Deleted!')` : After successful deletion, the view returns a response indicating that the post has been deleted.

![Delete post view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m55lsvowq8blhwzm506f.png)

After successful deletion


![Successful deletion](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsb9u2sl3uojyfuhksa4.png)

**Conclusion**

And there you have it, a REST API with full CRUD functionality.You can read more on django rest framework from their site [here](https://www.django-rest-framework.org/). From here on, I recommend building a similar api on your own to solidify your understanding. You can research on how to add more features such as file upload, user registration and login. You can also build a to do list api and connect it to the frontend using frontend frameworks such as React, Vue or just use plain JavaScript. The possibilities are endless, it your job to research and build bigger, better and more secure APIs. Happy coding!