Integrating Django with Reactjs using Django REST Framework

In this article, we will learn the process of communicating between the Django Backend and React js frontend using the Django REST Framework. For the sake of a better understanding of the concept, we will be building a Simple Task Manager and go through the primary concepts for this type of integration between React js and Django. Reactjs in a nutshell is a Javascript library for developing Single Page Applications(SPA) with very detailed and well-structured documentation. For this project, React will serve as the Frontend, handling the User Interface(UI) through the Request to Django’s backend.Project Overview:Let’s take a look first at what we will be building. The below images shows the UI of the Task Manager.This task manager application is a sort of to-do list. Here we will have three buttons as “Completed”,”Incomplete” and a button to add the task named “Add task” as shown in the above image. In order to add a task, you click on the Add task button which will open up a window within the app to add the task as shown below. Here we can add the “Title” for the task and give it a description inside the “Description” section. Finally, you can check or uncheck depending upon the status of the task(ie, Completed or Incomplete) as shown in the below image: After you “Save” the task, you can navigate between the Completed and Incomplete tabs to keep track of the tasks as shown below: Here you will also have the option to “Delete” or “Edit” and existing task as shown below: All of the operations performed above is managed by the Django REST Framework.Project Setup:Prerequisites:So the following are the prerequisites for the project:To verify if you have python 3 installed, use the following command in your command prompt( Since this project is developed on a Windows machine, we will be using the command prompt but depending upon your operating system you can use the terminal):python -VThis will show up the current python version on your system as shown below: To check if the Node module is installed, use the below command:node –versionThis will show you the node version on your system as shown below: At this point, we are good to go as we have Python and Node js installed in our system.Implementation:Let’s start with the Backend.Backend(Django):Now let’s open up our command prompt. Now follow the below steps in the same order to follow along with this article.Step 1: Create a directory named “django-react-app” using the below command(the command may change slightly depending upon your OS):mkdir django-react-appStep 2: Moved into the directory that we just created using the below command:cd django-react-projectStep 3: Now create a virtual environment using the below command:python -m venv darWe have named our virtual environment “dar”, short for Django and react. This is necessary as we don’t have to install packages and dependencies globally. It is also a good programming practice.Step 4: Activate the virtual environment that we just created using the below command:darScriptsactivate.batThis will activate our virtual machine as shown below: Step 5: Now install Django inside the virtual machine using the below command:pip install djangoYou will get a similar message as your installation gets completed: Step 6: Now let’s create our project named “backend” for our Django backend. To do so use the below command:django-admin startproject backendThe django-react-app will be our main folder and inside it, we will have two folders, one for the backend and one for the frontend that we will create later.Step 7: Now navigate to the backend folder using the below command:cd backendStep 8: Now we will start our app and call it “todo” using the below command:python startapp todoThe app gets created using the above command as shown below: Now let’s go ahead and start up the VS code and open the project folder inside it. At this stage our project structure will look like below:  Step 9: Now use the below command to migrate the project:python migrateThe migrations will be applied as shown below: Step 10: Now let’s run the server using the below command:python runserverNow you can visit the localhost to check if the project has started properly. As you can see in the below image the project is up and running: Step 11: Now we need to take some configuration steps inside the file. In the INSTALLED_APPS section add the name of the app that we created (ie, todo) as shown below:Python3  INSTALLED_APPS = [    ‘django.contrib.admin’,    ‘django.contrib.auth’,    ‘django.contrib.contenttypes’,    ‘django.contrib.sessions’,    ‘django.contrib.messages’,    ‘django.contrib.staticfiles’,    ‘todo’,]At this point, the file would look like below:Python3from pathlib import Path  BASE_DIR = Path(__file__).resolve().parent.parent      SECRET_KEY = ‘django-insecure-_c3!4)[email protected]@b6([email protected]+lxk1p==k+pyqko3’  DEBUG = True  ALLOWED_HOSTS = []      INSTALLED_APPS = [    ‘django.contrib.admin’,    ‘django.contrib.auth’,    ‘django.contrib.contenttypes’,    ‘django.contrib.sessions’,    ‘django.contrib.messages’,    ‘django.contrib.staticfiles’,    ‘todo’,]  MIDDLEWARE = [    ‘’,    ‘django.contrib.sessions.middleware.SessionMiddleware’,    ‘django.middleware.common.CommonMiddleware’,    ‘django.middleware.csrf.CsrfViewMiddleware’,    ‘django.contrib.auth.middleware.AuthenticationMiddleware’,    ‘django.contrib.messages.middleware.MessageMiddleware’,    ‘django.middleware.clickjacking.XFrameOptionsMiddleware’,]  ROOT_URLCONF = ‘backend.urls’  TEMPLATES = [    {        ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,        ‘DIRS’: [],        ‘APP_DIRS’: True,        ‘OPTIONS’: {            ‘context_processors’: [                ‘django.template.context_processors.debug’,                ‘django.template.context_processors.request’,                ‘django.contrib.auth.context_processors.auth’,                ‘django.contrib.messages.context_processors.messages’,            ],        },    },]  WSGI_APPLICATION = ‘backend.wsgi.application’      DATABASES = {    ‘default’: {        ‘ENGINE’: ‘django.db.backends.sqlite3’,        ‘NAME’: BASE_DIR / ‘db.sqlite3’,    }}      AUTH_PASSWORD_VALIDATORS = [    {        ‘NAME’: ‘django.contrib.auth.password_validation.UserAttributeSimilarityValidator’,    },    {        ‘NAME’: ‘django.contrib.auth.password_validation.MinimumLengthValidator’,    },    {        ‘NAME’: ‘django.contrib.auth.password_validation.CommonPasswordValidator’,    },    {        ‘NAME’: ‘django.contrib.auth.password_validation.NumericPasswordValidator’,    },]      LANGUAGE_CODE = ‘en-us’  TIME_ZONE = ‘UTC’  USE_I18N = True  USE_L10N = True  USE_TZ = True      STATIC_URL = ‘/static/’    DEFAULT_AUTO_FIELD = ‘django.db.models.BigAutoField’Step 12: Next, we will need to create a Model. The Model will determine how the todo items are stored in the database. We will have three properties in the model:Title: This will be the title of the task with a maximum length of 150 characters.Description: This will be the description of the task with a maximum length of 500 characters.Completed: This will be a boolean value, that will be used to determine the current status of the task. By default, it will be set to false.So go ahead and open the file and the following code:Python3class Todo(models.Model):    title=models.CharField(max_length=150)    description=models.CharField(max_length=500)    completed=models.BooleanField(default=False)We will also create a string representation of the title inside the Todo class as follows:Python3def __str__(self):      return self.title G”)At this point, our file will look like:Python3from django.db import models  class Todo(models.Model):    title=models.CharField(max_length=150)    description=models.CharField(max_length=500)    completed=models.BooleanField(default=False)          def __str__(self):                  return self.title Step 13: Now let’s go ahead and make migrations. Note that every time you make changes to the file, we will need to make migrations. Use the below command to do so:python makemigrationsThe following message will be generated when your migration is ready: Step 14: Now let’s apply all migrations using the below command:python migrateThis will apply our migrations as shown below: Now we can test to see that the CRUD operations work on the todo model file using the Admin site (or, the interface). For this we will need to register the models in the file.Step 15: Open up the file and add up the following code in it:Python3from django.contrib import admin  from .models import Todo  class TodoAdmin(admin.ModelAdmin):          list_display = (“title”,”description”,”completed”),TodoAdmin)Step 16: Now let’s create a superuser using the below command:python createsuperuserHere we will be using the following credentials:Username: GeeksEmail address: [email protected]:12345Note: You can set up your credentials as per your need. The above credentials need not be the same. We would get the following message when the superuser gets created: Step 17: Now let’s run the server and check everything is going as intended so far using the below command:python manage.p runserverNavigate to the following link: will show us the admin page as shown below: Here fill up your credentials and log in. We will use the credentials that we used while creating the superuser: This will lead us to the following page. Here we can see our users, the app, and the groups as shown below:Users: Todo: Let’s add some task to it and save it as shown below: We can see this task listed on the todo section as shown below: Creating the API:To create the API we will need to install the Django REST Framework for Serializers. We also need to django-cors-headers for whitelisting port 3000, which is the default port for React.Now follow the below steps to create the Django REST framework:Step 1:  To install the Django REST framework use the below command in the backend directory:pip install djangorestframeworkThe following message will be displayed once the installation is completed: Step 2: Now install the django-cors-headers using the below command:pip install django-cors-headersThe following message will be displayed once the installation is completed: Step 3: Now open up the file and add both the dependencies that we just installed to INSTALLED_APPS as shown below:Python3INSTALLED_APPS = [    ‘django.contrib.admin’,    ‘django.contrib.auth’,    ‘django.contrib.contenttypes’,    ‘django.contrib.sessions’,    ‘django.contrib.messages’,    ‘django.contrib.staticfiles’,    ‘todo’,    ‘corsheaders’,    ‘rest_framework’,]Step 4: Also in the file we need to whitelist the localhost port 3000. If we don’t do that there will be a block between the localhost:8000 and localhost:3000. Add the following code to achieve the same:Step 5: In the MIDDLEWARE section we need to add the cors-headers settings as shown below:Python3MIDDLEWARE = [    ‘’,    ‘django.contrib.sessions.middleware.SessionMiddleware’,    ‘django.middleware.common.CommonMiddleware’,    ‘django.middleware.csrf.CsrfViewMiddleware’,    ‘django.contrib.auth.middleware.AuthenticationMiddleware’,    ‘django.contrib.messages.middleware.MessageMiddleware’,    ‘django.middleware.clickjacking.XFrameOptionsMiddleware’,    ‘corsheaders.middleware.CorsMiddleware’]At this point, our would look like below:Python3from pathlib import Path  BASE_DIR = Path(__file__).resolve().parent.parent      SECRET_KEY = ‘django-insecure-_c3!4)[email protected]@b6([email protected]+lxk1p==k+pyqko3’  DEBUG = True  ALLOWED_HOSTS = []      INSTALLED_APPS = [    ‘django.contrib.admin’,    ‘django.contrib.auth’,    ‘django.contrib.contenttypes’,    ‘django.contrib.sessions’,    ‘django.contrib.messages’,    ‘django.contrib.staticfiles’,    ‘todo’,    ‘corsheaders’,    ‘rest_framework’,]  MIDDLEWARE = [    ‘’,    ‘django.contrib.sessions.middleware.SessionMiddleware’,    ‘django.middleware.common.CommonMiddleware’,    ‘django.middleware.csrf.CsrfViewMiddleware’,    ‘django.contrib.auth.middleware.AuthenticationMiddleware’,    ‘django.contrib.messages.middleware.MessageMiddleware’,    ‘django.middleware.clickjacking.XFrameOptionsMiddleware’,    ‘corsheaders.middleware.CorsMiddleware’]  ROOT_URLCONF = ‘backend.urls’  TEMPLATES = [    {        ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,        ‘DIRS’: [],        ‘APP_DIRS’: True,        ‘OPTIONS’: {            ‘context_processors’: [                ‘django.template.context_processors.debug’,                ‘django.template.context_processors.request’,                ‘django.contrib.auth.context_processors.auth’,                ‘django.contrib.messages.context_processors.messages’,            ],        },    },]  WSGI_APPLICATION = ‘backend.wsgi.application’      DATABASES = {    ‘default’: {        ‘ENGINE’: ‘django.db.backends.sqlite3’,        ‘NAME’: BASE_DIR / ‘db.sqlite3’,    }}      AUTH_PASSWORD_VALIDATORS = [    {        ‘NAME’: ‘django.contrib.auth.password_validation.UserAttributeSimilarityValidator’,    },    {        ‘NAME’: ‘django.contrib.auth.password_validation.MinimumLengthValidator’,    },    {        ‘NAME’: ‘django.contrib.auth.password_validation.CommonPasswordValidator’,    },    {        ‘NAME’: ‘django.contrib.auth.password_validation.NumericPasswordValidator’,    },]  CORS_ORIGIN_WHITELIST = ()    LANGUAGE_CODE = ‘en-us’  TIME_ZONE = ‘UTC’  USE_I18N = True  USE_L10N = True  USE_TZ = True      STATIC_URL = ‘/static/’    DEFAULT_AUTO_FIELD = ‘django.db.models.BigAutoField’Now we need to create the Sereilizers for the Todo data Model. The Serilaizers are responsible for Serializers is to create model instances to JSON. This will help the frontend to work with the received data easily. JSON is the standard for data interchange on the web.Step 6: Now create a file inside the todo folder and name it Inside the folder add the following code:Python3from rest_framework import serializers  from .models import Todo  class TodoSerializer(serializers.ModelSerializer):          class Meta:        model = Todo        fields = (‘id’, ‘title’,’description’,’completed’)Step 7: Now it’s time to create the Views. So open up the file. Now add the following code to the file:Python3from django.shortcuts import render  from rest_framework import viewsets  from .serializers import TodoSerializer  from .models import Todo  class TodoView(viewsets.ModelViewSet):              serializer_class = TodoSerializer              queryset = Todo.objects.all()Step 8: Now open up the file and add the following code to it.Python3from django.contrib import admin  from django.urls import path, include  from todo import views  from rest_framework import routers  router = routers.DefaultRouter()  router.register(r’tasks’,views.TodoView, ‘task’)  urlpatterns = [    path(‘admin/’,,                  path(‘api/’, include(router.urls))    ]This is the final step for creating the REST API and we can now perform all CRUD operations. Routers allow us to make queries. For example, if we go the the “tasks”, this will return the list of all the tasks. Also, you can have a single ‘task’ with an id to return a single task, where id is the primary key.Now let’s check if we are moving forward in the right direction. So run the server and navigate to the following URL:localhost:8000/apiIf everything is good, we will get the following outcome: As you can see our API is up and running.Now if we navigate to the following links we can view and interact with our tasks:locaLHOST:8000/api/tasks Frontend(React js):Now let’s build the frontend for our Todo app. For this follow the below steps:Step 1: Navigate to the main project directory(ie, django-react-app) and activate the virtual environment using the below command:darScriptsactivate.batStep 2: Now use the below command to create a boilerplate of React js app:npx create-react-app frontendHere, npx stands for Node Package Executable. After the boilerplate is setup you will get the following message: We will be also needing some UI flair for the UI design, specifically reactstrap and bootstrap.Step 3: So, use the below command to install reactstrap and bootstrap in the project:npm install reactstrap bootstrapStep 4: First move into the Frontend folder and use the below command to run the React server to make sure everything if working till this point:npm startIf everything is fine, you’ll get the following page on the localhost:3000 Step 5: Now open up the App.js file in the frontend folder. And clear the boilerplate code and change it to the below code:Javascriptimport “./App.css”;  function App() {  return Welcome to Geeksforgeeks!;}  export default App;At this point the frontend will look like below: As you can see in the above image. Any changes made to the App.js file are reflected directly to the UI.Step 6: Now the code to the App.js file. Comments are added to the code for better understanding.Javascriptimport React, { Component } from “react”;import Modal from “./components/Modal”;import axios from ‘axios’;    class App extends Component {      constructor(props) {    super(props);              this.state = {                        viewCompleted: false,      activeItem: {        title: “”,        description: “”,        completed: false      },                    taskList: []    };  }      componentDidMount() {    this.refreshList();  }       refreshList = () => {    axios         .then(res => this.setState({ taskList: }))      .catch(err => console.log(err));  };          displayCompleted = status => {    if (status) {      return this.setState({ viewCompleted: true });    }    return this.setState({ viewCompleted: false });  };        renderTabList = () => {    return (               this.displayCompleted(true)}          className={this.state.viewCompleted ? “active” : “”}        >          completed                     this.displayCompleted(false)}          className={this.state.viewCompleted ? “” : “active”}        >          Incompleted                      );  };    renderItems = () => {    const { viewCompleted } = this.state;    const newItems = this.state.taskList.filter(      (item) => item.completed === viewCompleted    );    return => (                        {item.title}                           this.editItem(item)}            className=”btn btn-secondary mr-2″          >            Edit                     this.handleDelete(item)}            className=”btn btn-danger”          >            Delete                            ));  };    toggle = () => {        this.setState({ modal: !this.state.modal });  };  handleSubmit = (item) => {    this.toggle();    alert(“save” + JSON.stringify(item));  };      handleSubmit = (item) => {    this.toggle();    if ( {            axios        .put(`http:        .then((res) => this.refreshList());      return;    }        axios      .then((res) => this.refreshList());  };      handleDelete = (item) => {    axios      .delete(`http:      .then((res) => this.refreshList());  };  handleDelete = (item) => {    alert(“delete” + JSON.stringify(item));  };      createItem = () => {    const item = { title: “”, description: “”, completed: false };    this.setState({ activeItem: item, modal: !this.state.modal });  };      editItem = (item) => {    this.setState({ activeItem: item, modal: !this.state.modal });  };      render() {    return (                        GFG Task Manager                                                                                      Add task                                            {this.renderTabList()}                              {this.renderItems()}                                                    {this.state.modal ? (                  ) : null}          );  }}export default App;Step 7: Now open up the Index.css file, clear the CSS inside it and add the following CSS in the file:CSS.todo-title {  cursor: pointer;}.completed-todo {  text-decoration: line-through;}.tab-list > span {  padding: 5px 8px;  border: 1px solid rgb(7, 167, 68);  border-radius: 10px;  margin-right: 5px;  cursor: pointer;}.tab-list > {  background-color: rgb(6, 139, 12);  color: #fff;}Step 8: Now create a new folder named “Components” in the src directory and add a file Modal.js to it. Then add the following code to it.Javascriptimport React, { Component } from “react”;  import {  Button,  Modal,  ModalHeader,  ModalBody,  ModalFooter,  Form,  FormGroup,  Input,  Label} from “reactstrap”;  class CustomModal extends Component {  constructor(props) {    super(props);    this.state = {      activeItem: this.props.activeItem    };  }    handleChange = e => {    let { name, value } =;    if ( === “checkbox”) {      value =;    }    const activeItem = { …this.state.activeItem, [name]: value };    this.setState({ activeItem });  };      render() {    const { toggle, onSave } = this.props;    return (               Task Item                                           {            }                          Title                                        {}                          Description                                        {}                                                          Completed                                                    {}                   onSave(this.state.activeItem)}>            Save                            );  }}export default CustomModalStep 10: Make the changes to the index.js file as follows:Javascriptimport React from “react”;import ReactDOM from “react-dom”;import “./index.css”;import App from “./App”;  import “bootstrap/dist/css/bootstrap.min.css”;   ReactDOM.render(        ,  document.getElementById(“root”));API Connection:For us to make requests to the API endpoints on the backend server of Django, we will need to install Axios. Use the following command inside the frontend folder to install Axios:npm install axiosOutput: Congratulation!!. At this point, you have successfully build a Fullstack Django-React app and Used the Django REST framework to establish communication between the frontend and backend. Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.  To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course. And to begin with your Machine Learning Journey, join the Machine Learning – Basic Level Course