The Talent500 Blog
How to make React.js work with Django via The Django REST framework? 1

How to make React.js work with Django via The Django REST framework?

Django is a Python backend web framework that is used to build secure and scalable website applications whereas React is a front-end Javascript framework that uses components in creating user interfaces for single-page applications.

We will be creating an application that consumes React for the user interface and Django for the API of our application using the Django REST framework (DRF).

Prerequisites

Following are the prerequisites needed to start with the project:

  • Python
  • Node.js
  • VS Code ( or, IDE of your choice)

Use the following command in your command prompt to verify if you have python installed.

python -V

It will show you the current python version in your system.

How to make React.js work with Django via The Django REST framework? 2

Use the below command to check if the Node module is installed 

node  –version

It will show you the node version installed in your system.

How to make React.js work with Django via The Django REST framework? 3

It is good to go now as we have python and Node js installed in our system.

We will be starting with the backend.

Implementing: Django(Backend)

Open your Command prompt and follow the given below steps:

Step 1: Using the below mention command create a directory named “Django-react-app” 

mkdir django-react-app

Step 2: Create the below command by moving into the directory 

cd Django-react-project

Step 3: Using the below mention command create a virtual environment 

python -m venv dar

Step 4: Below given command can be used to activate the virtual environment 

dar\Scripts\activate.bat

Step 5: Using the below mentioned install Django inside the virtual machine.

pip install Django

Step 6: Create a project for the Django backend by giving a name to the project. Use the command mentioned below:

django-admin startproject  “projectname”

There will be one folder of the Django-react app which will be the main folder and two subfolders: one for the backend and one for the front end which will be created later.

Step 7: Navigate to the backend folder using the below command:

cd backend

Step 8: Using the following command Start the app and call it “todo” 

python manage.py startapp todo

Step 9: To Migrate the project use the below command:

python manage.py migrate

Step 10: Run the server using the below command:

python manage.py runserver

Visit the local host to verify if the project has started properly. As you can see below image the project is up and running:

How to make React.js work with Django via The Django REST framework? 4

Step 11: Here take some configuration steps inside the file settings.py.

Add the name of the app “todo” in the INSTALLED_APPS section as shown below:

# Application definition

INSTALLED_APPS = [

    ‘django.contrib.admin’,

    ‘django.contrib.auth’,

    ‘django.contrib.contenttypes’,

    ‘django.contrib.sessions’,

    ‘django.contrib.messages’,

    ‘django.contrib.staticfiles’,

    ‘todo’,

The settings.py file at this point would look like the below:

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / ‘subdir’.

BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings – unsuitable for production

# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!

SECRET_KEY = ‘django-insecure-_c3!4)8+yce2l-ju@gz@b6(e0$00y@xhx7+lxk1p==k+pyqko3’

# SECURITY WARNING: don’t run with debug turned on in production!

DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [

    ‘django.contrib.admin’,

    ‘django.contrib.auth’,

    ‘django.contrib.contenttypes’,

    ‘django.contrib.sessions’,

    ‘django.contrib.messages’,

    ‘django.contrib.staticfiles’,

    ‘todo’,

]

MIDDLEWARE = [

    ‘django.middleware.security.SecurityMiddleware’,

    ‘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’

# Database

# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {

    ‘default’: {

        ‘ENGINE’: ‘django.db.backends.sqlite3’,

        ‘NAME’: BASE_DIR / ‘db.sqlite3’,

    }

}

# Password validation

# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

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’,

    },

]

# Internationalization

# https://docs.djangoproject.com/en/3.2/topics/i18n/ 

LANGUAGE_CODE = ‘en-us’

TIME_ZONE = ‘UTC’

USE_I18N = True 

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)

# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = ‘/static/’

# Default primary key field type

# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = ‘django.db.models.BigAutoField’

Step 12: Create a Model. The model will explain how the to-do items are stored in the database. There will be three properties in the model:

Title: Title of the task with 150 characters maximum length.

Description: Description of the task with 500 characters maximum length.

Completed: A Boolean value that is used to determine the status of the task. It will be set to false by default.

So go ahead and open the models.py file and the following code:

class Todo(models.Model):

    title=models.CharField(max_length=150)

    description=models.CharField(max_length=500)

    completed=models.BooleanField(default=False)

Create a string representation of the title inside the Todo class as follows:

def __str__(self):

  #it will return the title

  return self.title G”)

Our models.py file will look like this at this point:

from 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)

    # string representation of the class

    def __str__(self):

        #it will return the title

        return self.title

Step 13: Now make migrations. 

Note: every time you make changes to the models.py file, you need to make migrations. Make the migrations using the below command:

python manage.py makemigrations

A message will be generated when your migration is ready

Step 14: Using the below command, apply all migrations using the below command:

python manage.py migrate

This will apply your migrations

Do a test to see if CRUD operations work on the model file by using the admin site. Register the model in the admin.py file.

Step 15: Open the admin.py file and add the below mentioned code in it:

from Django.contrib import admin

# import the model Todo

from .models import Todo

# create a class for the admin-model integration

class TodoAdmin(admin.ModelAdmin):

    # add the fields of the model here

    list_display = (“title”,”description”,”completed”)

# we will need to register the

# model class and the Admin model class

# using the register() method

# of admin.site class

admin.site.register(Todo,TodoAdmin)

Step 16: Create a superuser by using below mention command:

python manage.py createsuperuser

Fill up the credentials

Username:

Email address:

Password:

Set up the credentials as per your need

You would receive a message when the superuser gets created:

Step 17: Run the server and check if everything is working properly by using the following command:

python manage.py runserver

The next step is to navigate the following link:

http://127.0.0.1:8000/admin/login/?next=/admin/

You will see an admin page

How to make React.js work with Django via The Django REST framework? 5

Fill up your credentials and log in. Use the credentials you have made while creating the superuser:

It will lead to the following page. You can see users, the app, and the groups as shown below:

Users:

How to make React.js work with Django via The Django REST framework? 6

Todo:

How to make React.js work with Django via The Django REST framework? 7

Now add some tasks to it and save it.

API Creation:

You need to install the Django REST framework. You also have Django-cors-headers for port 300 whitelisting as it is a default port for React.

Below are the steps to create the Django REST framework:

Step 1:  Use the below mention command to install the Django REST framework in the backend directory:

pip install djangorestframework

once the installation is completed a message will displayed:

Step 2: Now using below command install the Django-cors-headers using the below command:

pip install django-cors-headers

You will receive a message.

Step 3: Open the setting.py file and add both the dependencies that you have just installed to INSTALLED_APPS:

INSTALLED_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: Whitelist the localhost port 3000 in the settings.py file. 

Note: If you don’t whitelist, there will be a block between the localhost:8000 and localhost:3000. 

Now add the following code:

# White listing the localhost:3000 port

# for React

CORS_ORIGIN_WHITELIST = (

    ‘http://localhost:3000’,

 

Step 5: You need to add the cors-header in the MIDDLEWARE section:

 MIDDLEWARE = [

    ‘django.middleware.security.SecurityMiddleware’,

    ‘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’

]

Your settings.py will look like the below:

from pathlib import Path 

# Build paths inside the project like this: BASE_DIR / ‘subdir’.

BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings – unsuitable for production

# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!

SECRET_KEY = ‘django-insecure-_c3!4)8+yce2l-ju@gz@b6(e0$00y@xhx7+lxk1p==k+pyqko3’

# SECURITY WARNING: don’t run with debug turned on in production!

DEBUG = True

ALLOWED_HOSTS = []

# Application definition

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.middleware.security.SecurityMiddleware’,

    ‘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’

# Database

# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {

    ‘default’: {

        ‘ENGINE’: ‘django.db.backends.sqlite3’,

        ‘NAME’: BASE_DIR / ‘db.sqlite3’,

    }

}

# Password validation

# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

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’,

    },

]

# White listing the localhost:3000 port

CORS_ORIGIN_WHITELIST = (

    ‘http://localhost:3000’

)

# Internationalization

# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = ‘en-us’ 

TIME_ZONE = ‘UTC’

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)

# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = ‘/static/’

# Default primary key field type

# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = ‘django.db.models.BigAutoField’

Create Serializers for the data model. It is responsible for converting model instances to JSON. It will easily help the front end to work with the received data easily.

JSON is the standard for data interchange on the web.

Step 6: Create a file inside the todo folder and name it as Add the below code inside the folder. 

# import serializers from the REST framework

from rest_framework import serializers

# import the todo data model

from .models import Todo

# create a serializer class

class TodoSerializer(serializers.ModelSerializer):

    # create a meta class

    class Meta:

        model = Todo

        fields = (‘id’, ‘title’,’description’,’completed’) 

Step 7: Creating Views. Open up the views.py file. Add the below code to the file:

from django.shortcuts import render

# import view sets from the REST framework

from rest_framework import viewsets

# import the TodoSerializer from the serializer file

from .serializers import TodoSerializer

# import the Todo model from the models file

from .models import Todo

# create a class for the Todo model viewsets

class TodoView(viewsets.ModelViewSet):

    # create a serializer class and

    # assign it to the TodoSerializer class

    serializer_class = TodoSerializer

    # define a variable and populate it

    # with the Todo list objects

    queryset = Todo.objects.all() 

Step 8: Open the urls.py file and add the below code to it.

from django.contrib import admin

# add include to the path

from django.urls import path, include

# import views from todo

from todo import views

# import routers from the REST framework

# it is necessary for routing

from rest_framework import routers

# create a router object

router = routers.DefaultRouter()

# register the router

router.register(r’tasks’,views.TodoView, ‘task’)

urlpatterns = [

    path(‘admin/’, admin.site.urls),

    # add another path to the url patterns

    # when you visit the localhost:8000/api

    # you should be routed to the django Rest framework

    path(‘api/’, include(router.urls))

]

This will be the final step for creating the REST API and now you can now perform all CRUD operations. Routers allow us to make queries. 

At this step you need to check if you are moving forward in the right direction. Run the server and navigate to the following URL:

localhost:8000/api

You will get the below outcome:

You can see the API is up and running.

If you navigate to the following links, you can view and interact with your tasks:

locaLHOST:8000/api/tasks

Frontend(React js):

Building the frontend for the app. Follow the below mentioned steps.

Step 1: Activate the virtual environment to Navigate the main project directory(ie, Django-react-app) using the below command:

dar\Scripts\activate.bat

Step 2: Use the below command to create a boilerplate of React js app:

npx create-react-app frontend

Step 3: To install reactstrap and bootstrap in the project use the below command:

npm install reactstrap bootstrap

Step 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 start

Step 5: Open the App.js file in the frontend folder. Clear the boilerplate code and change it to the below code:

import “./App.css”;

function App() {

  return <div className=”App”><h2>Welcome to Geeksforgeeks!</h2></div>;

}

export default App;

Step 6: Now the code to the App.js file. Comments are added to the code for better understanding.

// import Component from the react module

import React, { Component } from “react”;

import Modal from “./components/Modal”;

import axios from ‘axios’; 

// create a class that extends the component

class App extends Component {

  // add a constructor to take props

  constructor(props) {

    super(props);

     

    // add the props here

    this.state = {   

      // the viewCompleted prop represents the status

      // of the task. Set it to false by default

      viewCompleted: false,

      activeItem: {

        title: “”,

        description: “”,

        completed: false

      },    

      // this list stores all the completed tasks

      taskList: []

    };

  }

  // Add componentDidMount()

  componentDidMount() {

    this.refreshList();

  }

  refreshList = () => {

    axios   //Axios to send and receive HTTP requests

      .get(“http://localhost:8000/api/tasks/”)

      .then(res => this.setState({ taskList: res.data }))

      .catch(err => console.log(err));

  };

  // this arrow function takes status as a parameter

  // and changes the status of viewCompleted to true

  // if the status is true, else changes it to false

  displayCompleted = status => {

    if (status) {

      return this.setState({ viewCompleted: true });

    }

    return this.setState({ viewCompleted: false });

  };

  // this array function renders two spans that help control

  // the set of items to be displayed(ie, completed or incomplete)

  renderTabList = () => {

    return (

      <div className=”my-5 tab-list”>

        <span

          onClick={() => this.displayCompleted(true)}

          className={this.state.viewCompleted ? “active” : “”}

        >

          completed

            </span>

        <span

          onClick={() => this.displayCompleted(false)}

          className={this.state.viewCompleted ? “” : “active”}

        >

          Incompleted

            </span>

      </div>

    );

  };

  // Main variable to render items on the screen

  renderItems = () => {

    const { viewCompleted } = this.state;

    const newItems = this.state.taskList.filter(

      (item) => item.completed === viewCompleted

    );

    return newItems.map((item) => (

      <li

        key={item.id}

        className=”list-group-item d-flex justify-content-between align-items-center”

      >

        <span

          className={`todo-title mr-2 ${

            this.state.viewCompleted ? “completed-todo” : “”

          }`}

          title={item.description}

        >

          {item.title}

        </span>

        <span>

          <button

            onClick={() => this.editItem(item)}

            className=”btn btn-secondary mr-2″

          >

            Edit

          </button>

          <button

            onClick={() => this.handleDelete(item)}

            className=”btn btn-danger”

          >

            Delete

          </button>

        </span>

      </li>

    ));

  };

  toggle = () => {

    //add this after modal creation

    this.setState({ modal: !this.state.modal });

  };

  handleSubmit = (item) => {

    this.toggle();

    alert(“save” + JSON.stringify(item));

  };

  // Submit an item

  handleSubmit = (item) => {

    this.toggle();

    if (item.id) {

      // if old post to edit and submit

      axios

        .put(`http://localhost:8000/api/tasks/${item.id}/`, item)

        .then((res) => this.refreshList());

      return;

    }

    // if new post to submit

    axios

      .post(“http://localhost:8000/api/tasks/”, item)

      .then((res) => this.refreshList());

  }; 

  // Delete item

  handleDelete = (item) => {

    axios

      .delete(`http://localhost:8000/api/tasks/${item.id}/`)

      .then((res) => this.refreshList());

  };

  handleDelete = (item) => {

    alert(“delete” + JSON.stringify(item));

  }; 

  // Create item

  createItem = () => {

    const item = { title: “”, description: “”, completed: false };

    this.setState({ activeItem: item, modal: !this.state.modal });

  };

  //Edit item

  editItem = (item) => {

    this.setState({ activeItem: item, modal: !this.state.modal });

  };

  // Start by visual effects to viewer

  render() {

    return (

      <main className=”content”>

        <h1 className=”text-success text-uppercase text-center my-4″>

          GFG Task Manager

        </h1>

        <div className=”row “>

          <div className=”col-md-6 col-sm-10 mx-auto p-0″>

            <div className=”card p-3″>

              <div className=””>

                <button onClick={this.createItem} className=”btn btn-info”>

                  Add task

                </button>

              </div>

              {this.renderTabList()}

              <ul className=”list-group list-group-flush”>

                {this.renderItems()}

              </ul>

            </div>

          </div>

        </div>

        {this.state.modal ? (

          <Modal

            activeItem={this.state.activeItem}

            toggle={this.toggle}

            onSave={this.handleSubmit}

          />

        ) : null}

      </main>

    );

  }

}

export default App; 

Step 7: Clear the CSS inside the Index.css file and add the below 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 > span.active {

  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.

import React, { Component } from “react”;

// importing all of these classes from reactstrap module

import {

  Button,

  Modal,

  ModalHeader,

  ModalBody,

  ModalFooter,

  Form,

  FormGroup,

  Input,

  Label

} from “reactstrap”;

// build a class base component

class CustomModal extends Component {

  constructor(props) {

    super(props);

    this.state = {

      activeItem: this.props.activeItem

    };

  }

  // changes handler to check if a checkbox is checked or not

  handleChange = e => {

    let { name, value } = e.target;

    if (e.target.type === “checkbox”) {

      value = e.target.checked;

    }

    const activeItem = { …this.state.activeItem, [name]: value };

    this.setState({ activeItem });

  };

  // rendering modal in the custommodal class received toggle and on save as props,

  render() {

    const { toggle, onSave } = this.props;

    return (

      <Modal isOpen={true} toggle={toggle}>

        <ModalHeader toggle={toggle}> Task Item </ModalHeader>

        <ModalBody>      

          <Form>

            {/* 3 formgroups

            1 title label */}

            <FormGroup>

              <Label for=”title”>Title</Label>

              <Input

                type=”text”

                name=”title”

                value={this.state.activeItem.title}

                onChange={this.handleChange}

                placeholder=”Enter Task Title”

              />

            </FormGroup> 

            {/* 2 description label */}

            <FormGroup>

              <Label for=”description”>Description</Label>

              <Input

                type=”text”

                name=”description”

                value={this.state.activeItem.description}

                onChange={this.handleChange}

                placeholder=”Enter Task Description”

              />

            </FormGroup>

            {/* 3 completed label */}

            <FormGroup check>

              <Label for=”completed”>

                <Input

                  type=”checkbox”

                  name=”completed”

                  checked={this.state.activeItem.completed}

                  onChange={this.handleChange}

                />

                Completed

              </Label>

            </FormGroup>

          </Form>

        </ModalBody>

        {/* create a modal footer */}

        <ModalFooter>

          <Button color=”success” onClick={() => onSave(this.state.activeItem)}>

            Save

          </Button>

        </ModalFooter>

      </Modal>

    );

  }

}

export default CustomModal 

Step 9: Make the changes to the index.js file as follows:

import React from “react”;

import ReactDOM from “react-dom”;

import “./index.css”;

import App from “./App”;

// importing css stylesheet to use the bootstrap class

// add this line only in this file

import “bootstrap/dist/css/bootstrap.min.css”;

ReactDOM.render(

  <React.StrictMode>

    <App />

  </React.StrictMode>,

  document.getElementById(“root”)

);

API Connection:

We will need to install Axios to make requests to the API endpoints on the Django backend server. To install Axios, use the below command inside the frontend folder:

npm install axios

Congratulations! You have successfully built a Fullstack Django-React app and used the Django REST framework to establish communication between the frontend and backend!

 

 

 

0
Subhojit Hazra

Subhojit Hazra

He is a tech enthusiast and a passionate marketer with an eye for detail. He loves to uncomplicate things and debate on business problems. A quiet guy who likes peaceful evenings and iced coffees.

Add comment