Create Django REST API (Todo APP)
Tags: webdev, django, showdev, python
Published: 2021-01-29 10:03:20

---
title: Create Django REST API (Todo APP)
published: true
description: in this post, we'll explore how can we create APIs endpoints for our Todo App.
tags: #webdev #django #showdev #python 
cover_image: https://i.morioh.com/2019/12/06/af3f12467e70.jpg
---

In this article, I'm gonna create REST APIs in the Django framework more likely in Django-rest-framework. What I discovered while learning Django is Robust Framework and I sound like "WoW". how, ... wait let's create and I bet you that you will sound the same as I did.

### Prerequisite

make sure you've already installed python3.8+, now let's create an isolated environment for our project so it won't hurt our OS. you can install `pipenv` through your OS package manager like `apt`, `brew` or you can do it through the `pip3` package 

![carbon](https://dev-to-uploads.s3.amazonaws.com/i/dsq46w7sgh03dwh6dgw9.png)
 

### Get started

Now, create a directory for our Todo app
![carbon (1)](https://dev-to-uploads.s3.amazonaws.com/i/lhrjdk5tp19y4wpg2lrn.png)


let's install the Django framework in the todo directory and activate the virtual environmental
![carbon (2)](https://dev-to-uploads.s3.amazonaws.com/i/2mbqznr4gskc6w2wjapg.png)
  
Boom, we're inside the virtual environmental, if you see parentheses in your command. we should start out by creating the Django traditional project named `todo_project` and adding the `todos` app (App is where we create all our code)  and migrating our initial database

![carbon (3)](https://dev-to-uploads.s3.amazonaws.com/i/lpvp6by5jhijddvat6o5.png)

In Django, we always need to add a new app inside `INSTALLED_APPS`. to do so, open up `todo/todo_project/settings.py` and add at the bottom.

```python
# todo_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

# Local
'todos', # new app added here
]
```

So far so good, let's give it shot, if you've done everything right, you should be able to run the below command without any issue:
![run server](https://dev-to-uploads.s3.amazonaws.com/i/pcu2s9bb6oa48obgbe7z.png)
, 

head over to `http://127.0.0.1:8000/` And Boom There you have your first Django project, Awesome. Now let's create a Model; Model is where we create our Database Structure (same is Scheme in NodeJS).

open up your model file `todo/todos/models.py`:

```python
# todo/todos/models.py

from django.db import models

class Todo(models.Model):
    title = models.CharField(max_length=250)
    body = models.TextField()

    def __str__(self):
        return self.title

```

first, we import the `models` then we created `title` and `body` for our Todo-app. `CharField` is character with max_length, `TextField` is text (suppose it like `textarea` in HTML). we have to add `Field` at the end of everything like `Boolean` to `BooleanField()`. and the [`__str__`](https://stackoverflow.com/questions/45483417/what-is-doing-str-function-in-django) return the title when you instance the model.

Now Register the Todo model in the admin `todo/todos/admin.py`

```python
# todo/todos/admin.py

from django.contrib import admin

from .models import Todo
# Register your models here.


class TodoAdmin(admin.ModelAdmin):
    list_display = ('title', 'body')


admin.site.register(Todo, TodoAdmin)

```
`list_display` will give us the `title` and `body` on the admin page in the column, more user-friendly. migrate the charges, every time we made some changes in the model. we have to migrate

![carbon (4)](https://dev-to-uploads.s3.amazonaws.com/i/hzh7lslloppf8k3fv8qo.png)


now, create a user for the admin page with username and password, so do it:
![carbon (5)](https://dev-to-uploads.s3.amazonaws.com/i/3pjqfy4fbpitjty4kz1s.png)
  
now run the server and head over to `http://127.0.0.1:8000/admin`:
![run server](https://dev-to-uploads.s3.amazonaws.com/i/4wc4kt7076bkswq3kjbb.png)
 
it'll ask you for credentials, just put what you've created in the previous command. and click on the `todos` in the right column like below and the `list_display` magic see here:
![Screenshot from 2021-01-29 12-16-12](https://dev-to-uploads.s3.amazonaws.com/i/b5o69czi23cdc9hwwffk.png)
 
It's time to install the Django-rest-framework for APIS and CORS lib for [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) problem:
![carbon (7)](https://dev-to-uploads.s3.amazonaws.com/i/bdiw3oxf4cnvhd3tb57v.png)

```python
# todo_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

# 3rd party
'rest_framework', # new added
'corsheaders', # new added

# Local
'todos',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # new added
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
```
and allow the URLs to make a request for the backend and frontend
```python
# new
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
'http://localhost:8000',
)
```

The next step is to Configure URL for our API endpoints in `todo_project/urls.py`.
```python
# todo_project/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('todos.urls'))
]
```

we imported `todos.urls` file, we yet have to create, so let's create `todos/urls.py` and add these line:
```python
# todos/urls.py

from django.urls import path
from .views import ListTodo, DetailTodo, CreateTodo


urlpatterns = [
    path('<int:pk>/', DetailTodo.as_view()),
    path('', ListTodo.as_view()),
    path('create', CreateTodo.as_view())
]

```
we imported the `ListTodo, DetailTodo` and `CreateTodo` which we yet have to create these classes. and `urlspatterns` is where we create our routs. `<int:pk>` is passing the Primary key as a URL query.

#### Serializer (JSON)
we need a serializer file to transpile the python queryset to JSON in order to send it over HTTP request. let's go ahead and create a file `todos/serializer.py`
```python
from rest_framework import serializers
from .models import Todo


class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ('id', 'title', 'body')

```

Importing the Todo Model and exposing the `id, title, body` field as JSON in the `Meta` class. `model` variable is which model we need to transpile and fields is which fields we need to expose. `id` field is created automatically when adding new object

#### View

open the `todos/views.py` file and the logic
```python
from rest_framework import generics
from .serializers import TodoSerializer
from .models import Todo


# Showing the List
class ListTodo(generics.ListAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

# fetching single todo
class DetailTodo(generics.RetrieveAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

# creating one
class CreateTodo(generics.CreateAPIView):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer

```

now run the server and head over to 'http://127.0.0.1:8000/api/create`
![run server](https://dev-to-uploads.s3.amazonaws.com/i/njfdebzojknelr4iueyn.png)

![Screenshot from 2021-01-29 15-03-00](https://dev-to-uploads.s3.amazonaws.com/i/pqa3k9vtpoo0wvsbo16h.png)
 
it will let you create a new todo, and play around with. isn't it cool! we didn't create any logic to create a new todo. this is how it wins. to read more about [generics](https://www.django-rest-framework.org/api-guide/generic-views/) Github Repo: https://github.com/lifeeric/django-rest-api/

Thanks for following along with me, if you found any error, mistake, please fix me I'll be happy!

if you found something for me, let do it together!