DEV Community

Cover image for How to create a CRUD application in ReactJS and Django Rest Framework
Madhuban Khatri
Madhuban Khatri

Posted on • Edited on

7 1 1 1 1

How to create a CRUD application in ReactJS and Django Rest Framework

In this post, I am creating a simple CRUD application with the help of ReactJs and Django Rest Framework. We will divide this post into two parts - Frontend and Backend.

In the frontend part, we will use ReactJS for client-side handling and API calls. Conversely, the Backend part will use the Django rest framework for making APIs.

Before starting the tutorial we have to install some packages/libraries in Frontend and Backend.
For Frontend, we need to install-

  • axios - for API calls
  • react-router-dom - for routing between the pages

For Backend, we need to install-


Frontend

App.js

import './App.css';
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
import Home from './Components/Home';
import About from './Components/About';
import Contact from './Components/Contact';
import Edit from './Components/Edit';
import Root from './Components/Root';

function App() {
  const url = "http://127.0.0.1:8000/"

  const router = createBrowserRouter(createRoutesFromElements(
    <Route path="/" element={<Root/>}>
      <Route index element={<Home url={url}/>}/>
      <Route path="/about"  element={<About/>}/>
      <Route path="/contact"  element={<Contact/>}/>
      <Route path="/edit/:id/"  element={<Edit url={url}/>}/>
    </Route>
  ))

  return (
    <div>
        <RouterProvider router={router}/>       
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Components/Root.js

import { Link, Outlet } from "react-router-dom";
function Root(){
    return(
        <>
            <nav className="navbar navbar-expand-lg bg-body-tertiary" data-bs-theme="dark">
                <div className="container-fluid">
                    <a className="navbar-brand" href="#">React+DRF</a>
                    <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                        <span className="navbar-toggler-icon"></span>
                    </button>
                    <div className="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul className="navbar-nav me-auto mb-2 mb-lg-0">
                            <li className="nav-item">
                                <Link to='/' className="nav-link active" aria-current="page" href="#">Home</Link>
                            </li>
                            <li className="nav-item">
                                <Link to='/about' className="nav-link active" href="#">About</Link>
                            </li>
                            <li className="nav-item">
                                <Link to='/contact' className="nav-link active" href="#">Contact</Link>
                            </li>
                        </ul>
                    </div>
                </div>
            </nav>


        <div>
            <Outlet/>
        </div>
        </>
    )
}
export default Root;
Enter fullscreen mode Exit fullscreen mode

Components/Home.js

import axios from "axios";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";

function Home(props){
    useEffect(()=>{
        getData();
    },[])

    const [users, setUsers] = useState([]);
    const [username, setUsername] = useState();
    const [password, setPassword] = useState();

    // Fetching the data from DRF API
    async function getData(){
        const response = await axios.get(props.url);
        setUsers(response.data);
    }

    // Posting the data to DRF API
    async function handleSubmit(e){
        e.preventDefault();
        let data = {
            user_name: username,
            password: password
        }
        await axios.post(props.url+'create_user/', data, {
            headers:{
                'Content-Type': 'multipart/form-data'
            }
        });
        getData();
    }

    //Delete a specific user
    const deleteUser=(user_id)=>{
      axios.delete(props.url+`delete_user/${user_id}/`, {id:user_id})
      .then(()=>getData())
      .catch((err)=>console.log(err))

    }
    return(

        <div className="container w-50 my-5">
            <form onSubmit={handleSubmit}>
            <div className="mb-3">
                <label htmlFor="exampleFormControlInput1" className="form-label">Username</label>
                <input type="text" className="form-control" id="exampleFormControlInput1" value={username} onChange={(e)=>setUsername(e.target.value)} placeholder="Username"/>
            </div>

            <div className="mb-3">
                <label htmlFor="exampleFormControlInput2" className="form-label">Password</label>
                <input type="password" className="form-control" id="exampleFormControlInput2" value={password} onChange={(e)=>setPassword(e.target.value)} placeholder="Password"/>
            </div>
            <input type="submit" className="btn btn-primary form-control" value="ADD"/>
            </form>

            <br/>
            <table className="table text-center" border={1} cellPadding={5}>
                <tbody>
                <tr>
                    <th>Id</th>
                    <th>Username</th>
                    <th>Password</th>
                    <th>Operation</th>
                </tr>

                {
                    users.map((user=>{
                        return(
                            <tr key={user.id}>
                                <td>{user.id}</td>
                                <td>{user.user_name}</td>
                                <td>{user.password}</td>
                                <td>
                                    <Link className="btn btn-sm btn-primary mx-3" to={`/edit/${user.id}`} state={{uname: user.user_name, pwd: user.password}}>Edit</Link>
                                    <button className="btn btn-sm btn-danger" onClick={()=>deleteUser(user.id)}>Delete</button>
                                </td>
                            </tr>
                        )
                    }))
                }
                </tbody>
            </table>
            </div>
    )
}
export default Home;
Enter fullscreen mode Exit fullscreen mode

Components/Edit.js

import axios from "axios";
import { useState } from "react";
import { useLocation, useParams, useNavigate } from "react-router-dom";
function Edit(props) {
    const location = useLocation();
    const userId = useParams()
    const [username, setUsername] = useState(location.state.uname);
    const [password, setPassword] = useState(location.state.pwd);
    const navigate = useNavigate();

    const updateUser = async (e) =>{
        e.preventDefault()
        const response = await axios.put(props.url+`update_user/${userId.id}/`, {user_name: username, password: password});
        navigate("/")
    }


    return(
        <div className="container w-50 my-5">
            <form onSubmit={updateUser}>
                <div className="mb-3">
                    <label for="exampleFormControlInput1" className="form-label">Username</label>
                    <input type="text" className="form-control" id="exampleFormControlInput1" value={username} onChange={(e)=>setUsername(e.target.value)} placeholder="Username"/>
                </div>

                <div className="mb-3">
                    <label for="exampleFormControlInput2" className="form-label">Password</label>
                    <input type="password" className="form-control" id="exampleFormControlInput2" value={password} onChange={(e)=>setPassword(e.target.value)} placeholder="Password"/>
                </div>
                <input type="submit" className="btn btn-primary form-control" value="Update"/>
            </form>
        </div>
    )
}

export default Edit;
Enter fullscreen mode Exit fullscreen mode

Components/About.js

function About(){
    return(
        <h1>About page</h1>
    )
}
export default About;
Enter fullscreen mode Exit fullscreen mode

Components/Contact.js

function Contact(){
    return(
        <h1>Contact page</h1>
    )
}
export default Contact;
Enter fullscreen mode Exit fullscreen mode

Backend

settings.py

We have to create a main app in our project and add main, rest_framework and corsheaders in INSTALLED_APPS and also add some MIDDLEWARE in settings.py.

INSTALLED_APPS = [
    .
    .
    'main',
    'rest_framework',
    'corsheaders'
]
CORS_ALLOW_ALL_ORIGINS=True


MIDDLEWARE = [
    .
    .
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',    
]
Enter fullscreen mode Exit fullscreen mode

project's urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('main.urls')),
]

Enter fullscreen mode Exit fullscreen mode

models.py

Create a MyUser model that contains user_name and password.

from django.db import models

class MyUser(models.Model):
    user_name = models.CharField(max_length=50)
    password = models.CharField(max_length=50)

    def __str__(self):
        return self.user_name

Enter fullscreen mode Exit fullscreen mode

admin.py

Register above model in admin.py file like this-

from django.contrib import admin
from .models import MyUser
admin.site.register(MyUser)
Enter fullscreen mode Exit fullscreen mode

serializers.py

from rest_framework import serializers
from .models import MyUser

class MyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyUser
        fields = "__all__"

Enter fullscreen mode Exit fullscreen mode

views.py

from .models import MyUser
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import MyUserSerializer

@api_view(['GET'])
def getData(request):
    users = MyUser.objects.all()
    users_serializer = MyUserSerializer(users, many=True)
    return Response(users_serializer.data)


@api_view(['POST'])    
def create_user(request):
    if request.method=='POST':
        data=request.data
        serializer = MyUserSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response("Errrro")


@api_view(['PUT'])    
def update_user(request, id):
    if request.method=='PUT':
        data=request.data
        user_obj = MyUser.objects.get(id=id)
        serializer = MyUserSerializer(user_obj, data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response("Errrro")

@api_view(['DELETE'])    
def delete_user(request, id):
    if request.method=='DELETE':
        data=request.data
        user_obj = MyUser.objects.get(id=id)
        user_obj.delete()
        return Response("Delete succesffully")
Enter fullscreen mode Exit fullscreen mode

urls.py

from django.urls import path
from . import views

urlpatterns  = [
    path('', views.getData),
    path('create_user/', views.create_user),
    path('update_user/<int:id>/', views.update_user),
    path('delete_user/<int:id>/', views.delete_user),
]
Enter fullscreen mode Exit fullscreen mode

To run react server you have to open frontend directory in cmd and run this command - npm start
To run backend server you have to open backend directory in cmd and run this command - python manage.py runserver

Code is also available on Github

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay