DevGang
Авторизоваться

Как создать CRUD-приложение на ReactJS и Django Rest Framework

В этом посте я создаю простое CRUD-приложение с помощью ReactJs и Django Rest Framework. Мы разделим этот пост на две части - Frontend и Backend.

Во фронтенд-части мы будем использовать ReactJS для работы на стороне клиента и вызова API. И наоборот, в бэкенд-части для создания API будет использоваться фреймворк Django Rest.

Перед началом обучения нам необходимо установить некоторые пакеты/библиотеки в папки фронтенда и бэкенда.

Для фронтенда нам необходимо установить:

  • axios - для вызовов API
  • react-router-dom - для маршрутизации между страницами

Для бэкенда нам необходимо установить:

Фронтенд

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;

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;

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;

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;

Components/About.js

function About(){
    return(
        <h1>About page</h1>
    )
}
export default About;

Components/Contact.js

function Contact(){
    return(
        <h1>Contact page</h1>
    )
}
export default Contact;

Бэкенд

settings.py

Мы должны создать приложение main в нашем проекте и добавить main, rest_framework и corsheaders в INSTALLED_APPS, а также добавить MIDDLEWARE в settings.py.

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


MIDDLEWARE = [
    .
    .
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',    
]

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')),
]

models.py

Создайте модель MyUser, содержащую user_name и 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

admin.py

Зарегистрируйте указанную модель в файле admin.py следующим образом:

from django.contrib import admin
from .models import MyUser
admin.site.register(MyUser)

serializers.py

from rest_framework import serializers
from .models import MyUser

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

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

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),
]

Для запуска react-сервера необходимо открыть каталог frontend в cmd и выполнить команду npm start.

Для запуска сервера backend необходимо открыть директорию backend в cmd и выполнить следующую команду - python manage.py runserver.

Источник:

#React #Django
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу