In this tutorial, you will learn to create a full stack web application from scratch using SQLite DB for the database, Python Django for the backend, and React JS for the front end.
We will first start with creating the backend project with
Django and create the required rest API end points. And then we will use React
JS for creating the front end project.
-You will learn how to add routing for our app.
-Create bootstrap table with custom sorting and filtering
capabilities.
-Add modal pop up windows with drop downs and date pickers.
-We will also learn how to upload an image and store it in
the backend server.
Lets install the necessary modules needed for our Django project.
First lets install the Django module.
>> pip install django
To create rest APIs we need to install Django rest framework.
>> pip install djangorestframework
By default, the Django project comes with a security that blocks requests coming from different domains. To disable this, lets install Django CORS headers module.
>> pip install django-cors-headers
Now lets create the Django project.
Open the command prompt in the desired folder and type the command.
>> django-admin start project <name of the project>
Lets take a look at some of the important files in the project.
>> __init__.py file is just and empty file that indicates that the given folder is a python project or a python module.
>> asgi.py is the entry point for the asgi compatible webservers.
>> wsgi.py is the entry point for the wsgi compatible web servers.
>> urls.py file contains all the url declarations needed for this project.
>> settings.py file contains all the settings or the configurations needed for the project.
>> manage.py is a command line utility that helps interact with the Django project.
Lets simply run the project and see how it looks in the browser using below command.
>> python manage.py runserver
The app is now running in the port 8000.
Lets copy the url and open in the browser.
What you see on the screen is the default template that comes with every Django project.
Now lets create an app in our Django project.
Quick difference between projects and apps.
The folder structure that you currently see on the screen is called the project.
A project may have multiple apps.
For example, you can have one app which acts like a blog, or may be another app which acts like a survey form.
Currently this project does not have any app.
Lets create one app to implement our api methods.
To create an app, we need to type this command.
>> python manage.py startapp <the name of the app>
Next let us register the app and the required modules in settings.py file.
In the installed apps section, lets add Rest framework, cors header, and the newly created app.
We need to add the cors headers in middle ware section as well.
We will also add instruction to enable all domains to access the APIs.
This is not recommended in production. Instead, just add only those domains that needs to be whitelisted.
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'corsheaders', 'EmployeeApp.apps.EmployeeappConfig' ] CORS_ORIGIN_ALLOW_ALL = True MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', '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', ]
Lets create the models needed for our app.
We need two models.
One to store department details and another one to store employee details.
The departments model will have two fields. One to store an autoincremented Department ID, and another one to store Department Name.
Employee model will have five fields.
Employee ID, Employee name, Department, Date of joining, and photo file name which stores the uploaded profile picture file name.
Models.py complete code:
from django.db import models # Create your models here. class Departments(models.Model): DepartmentId = models.AutoField(primary_key=True) DepartmentName = models.CharField(max_length=500) class Employees(models.Model): EmployeeId = models.AutoField(primary_key=True) EmployeeName = models.CharField(max_length=500) Department = models.CharField(max_length=500) DateOfJoining = models.DateField() PhotoFileName = models.CharField(max_length=500)
We will be using the default SQLite database that comes with our Django project.
We can see that it is already registered in the database section of settings.py file.
Lets write the command to make migrations file for our models.
>> python manage.py makemigrations <app name>
After executing this, we can see a migration file which tells us what changes to the database will be done.
Once it looks fine, we can execute the command to push these changes to the database.
>> python manage.py migrate <app name>
Lets create serializers for our models.
Serializers basically help to convert the complex types or model instances into native python data types that can then be easily rendered into json or xml or other content types.
They also help in deserialization which is nothing but converting the passed data back to complex types.
serializers.py complete code:
from rest_framework import serializers from EmployeeApp.models import Departments,Employees class DepartmentSerializer(serializers.ModelSerializer): class Meta: model=Departments fields=('DepartmentId','DepartmentName') class EmployeeSerializer(serializers.ModelSerializer): class Meta: model=Employees fields=('EmployeeId','EmployeeName','Department','DateOfJoining','PhotoFileName')
Lets now start writing the API methods.
views.py code.
from django.shortcuts import render from django.views.decorators.csrf import csrf_exempt from rest_framework.parsers import JSONParser from django.http.response import JsonResponse from EmployeeApp.models import Departments,Employees from EmployeeApp.serializers import DepartmentSerializer,EmployeeSerializer from django.core.files.storage import default_storage # Create your views here. @csrf_exempt def departmentApi(request,id=0): if request.method=='GET': departments = Departments.objects.all() departments_serializer=DepartmentSerializer(departments,many=True) return JsonResponse(departments_serializer.data,safe=False) elif request.method=='POST': department_data=JSONParser().parse(request) departments_serializer=DepartmentSerializer(data=department_data) if departments_serializer.is_valid(): departments_serializer.save() return JsonResponse("Added Successfully",safe=False) return JsonResponse("Failed to Add",safe=False) elif request.method=='PUT': department_data=JSONParser().parse(request) department=Departments.objects.get(DepartmentId=department_data['DepartmentId']) departments_serializer=DepartmentSerializer(department,data=department_data) if departments_serializer.is_valid(): departments_serializer.save() return JsonResponse("Updated Successfully",safe=False) return JsonResponse("Failed to Update") elif request.method=='DELETE': department=Departments.objects.get(DepartmentId=id) department.delete() return JsonResponse("Deleted Successfully",safe=False) @csrf_exempt def employeeApi(request,id=0): if request.method=='GET': employees = Employees.objects.all() employees_serializer=EmployeeSerializer(employees,many=True) return JsonResponse(employees_serializer.data,safe=False) elif request.method=='POST': employee_data=JSONParser().parse(request) employees_serializer=EmployeeSerializer(data=employee_data) if employees_serializer.is_valid(): employees_serializer.save() return JsonResponse("Added Successfully",safe=False) return JsonResponse("Failed to Add",safe=False) elif request.method=='PUT': employee_data=JSONParser().parse(request) employee=Employees.objects.get(EmployeeId=employee_data['EmployeeId']) employees_serializer=EmployeeSerializer(employee,data=employee_data) if employees_serializer.is_valid(): employees_serializer.save() return JsonResponse("Updated Successfully",safe=False) return JsonResponse("Failed to Update") elif request.method=='DELETE': employee=Employees.objects.get(EmployeeId=id) employee.delete() return JsonResponse("Deleted Successfully",safe=False) @csrf_exempt def SaveFile(request): file=request.FILES['file'] file_name=default_storage.save(file.name,file) return JsonResponse(file_name,safe=False)
""" Django settings for DjangoAPI project. Generated by 'django-admin startproject' using Django 3.2.4. For more information on this file, see https://docs.djangoproject.com/en/3.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.2/ref/settings/ """ from pathlib import Path import os BASE_DIR=Path(__file__).resolve(strict=True).parent.parent MEDIA_URL='/Photos/' MEDIA_ROOT=os.path.join(BASE_DIR,"Photos") # 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-@oxx-o(4f=mxha%-tlv97)x9m7x_fw=(@*k=*29q%r7c8*)%-&' # 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', 'rest_framework', 'corsheaders', 'EmployeeApp.apps.EmployeeappConfig' ] CORS_ORIGIN_ALLOW_ALL = True MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', '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 = 'DjangoAPI.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 = 'DjangoAPI.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'
from django.conf.urls import url from EmployeeApp import views from django.conf.urls.static import static from django.conf import settings urlpatterns=[ url(r'^department$',views.departmentApi), url(r'^department/([0-9]+)$',views.departmentApi), url(r'^employee$',views.employeeApi), url(r'^employee/([0-9]+)$',views.employeeApi), url(r'^employee/savefile',views.SaveFile) ]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
"""DjangoAPI URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/3.2/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path from django.conf.urls import url,include urlpatterns = [ path('admin/', admin.site.urls), url(r'^',include('EmployeeApp.urls')) ]
React JS Front End:
Create react js project with below command:
> npx create-react-app my-app
my-app is the name of our project.
Folder structure of the project:
<!DOCTYPE html> <html lang="en"> <head> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <meta charset="utf-8" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="theme-color" content="#000000" /> <meta name="description" content="Web site created using create-react-app" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <!-- manifest.json provides metadata used when your web app is installed on a user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ --> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <!-- Notice the use of %PUBLIC_URL% in the tags above. It will be replaced with the URL of the `public` folder during the build. Only files inside the `public` folder can be referenced from the HTML. Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> <title>React App</title> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. To begin the development, run `npm start` or `yarn start`. To create a production bundle, use `npm run build` or `yarn build`. --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> </body> </html>
import React,{Component} from 'react'; export class Home extends Component{ render(){ return( <div> <h3>This is Home page</h3> </div> ) } }
import React,{Component} from 'react'; export class Department extends Component{ render(){ return( <div> <h3>This is Department page</h3> </div> ) } }
import React,{Component} from 'react'; export class Employee extends Component{ render(){ return( <div> <h3>This is Employee page</h3> </div> ) } }
import logo from './logo.svg'; import './App.css'; import {Home} from './Home'; import {Department} from './Department'; import {Employee} from './Employee'; import {BrowserRouter, Route, Switch,NavLink} from 'react-router-dom'; function App() { return ( <BrowserRouter> <div className="App container"> <h3 className="d-flex justify-content-center m-3"> React JS Frontend </h3> <nav className="navbar navbar-expand-sm bg-light navbar-dark"> <ul className="navbar-nav"> <li className="nav-item- m-1"> <NavLink className="btn btn-light btn-outline-primary" to="/home"> Home </NavLink> </li> <li className="nav-item- m-1"> <NavLink className="btn btn-light btn-outline-primary" to="/department"> Department </NavLink> </li> <li className="nav-item- m-1"> <NavLink className="btn btn-light btn-outline-primary" to="/employee"> Employee </NavLink> </li> </ul> </nav> <Switch> <Route path='/home' component={Home}/> <Route path='/department' component={Department}/> <Route path='/employee' component={Employee}/> </Switch> </div> </BrowserRouter> ); } export default App;
import React,{Component} from 'react'; import {variables} from './Variables.js'; export class Department extends Component{ constructor(props){ super(props); this.state={ departments:[], modalTitle:"", DepartmentName:"", DepartmentId:0, DepartmentIdFilter:"", DepartmentNameFilter:"", departmentsWithoutFilter:[] } } FilterFn(){ var DepartmentIdFilter=this.state.DepartmentIdFilter; var DepartmentNameFilter = this.state.DepartmentNameFilter; var filteredData=this.state.departmentsWithoutFilter.filter( function(el){ return el.DepartmentId.toString().toLowerCase().includes( DepartmentIdFilter.toString().trim().toLowerCase() )&& el.DepartmentName.toString().toLowerCase().includes( DepartmentNameFilter.toString().trim().toLowerCase() ) } ); this.setState({departments:filteredData}); } sortResult(prop,asc){ var sortedData=this.state.departmentsWithoutFilter.sort(function(a,b){ if(asc){ return (a[prop]>b[prop])?1:((a[prop]<b[prop])?-1:0); } else{ return (b[prop]>a[prop])?1:((b[prop]<a[prop])?-1:0); } }); this.setState({departments:sortedData}); } changeDepartmentIdFilter = (e)=>{ this.state.DepartmentIdFilter=e.target.value; this.FilterFn(); } changeDepartmentNameFilter = (e)=>{ this.state.DepartmentNameFilter=e.target.value; this.FilterFn(); } refreshList(){ fetch(variables.API_URL+'department') .then(response=>response.json()) .then(data=>{ this.setState({departments:data,departmentsWithoutFilter:data}); }); } componentDidMount(){ this.refreshList(); } changeDepartmentName =(e)=>{ this.setState({DepartmentName:e.target.value}); } addClick(){ this.setState({ modalTitle:"Add Department", DepartmentId:0, DepartmentName:"" }); } editClick(dep){ this.setState({ modalTitle:"Edit Department", DepartmentId:dep.DepartmentId, DepartmentName:dep.DepartmentName }); } createClick(){ fetch(variables.API_URL+'department',{ method:'POST', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' }, body:JSON.stringify({ DepartmentName:this.state.DepartmentName }) }) .then(res=>res.json()) .then((result)=>{ alert(result); this.refreshList(); },(error)=>{ alert('Failed'); }) } updateClick(){ fetch(variables.API_URL+'department',{ method:'PUT', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' }, body:JSON.stringify({ DepartmentId:this.state.DepartmentId, DepartmentName:this.state.DepartmentName }) }) .then(res=>res.json()) .then((result)=>{ alert(result); this.refreshList(); },(error)=>{ alert('Failed'); }) } deleteClick(id){ if(window.confirm('Are you sure?')){ fetch(variables.API_URL+'department/'+id,{ method:'DELETE', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' } }) .then(res=>res.json()) .then((result)=>{ alert(result); this.refreshList(); },(error)=>{ alert('Failed'); }) } } render(){ const { departments, modalTitle, DepartmentId, DepartmentName }=this.state; return( <div> <button type="button" className="btn btn-primary m-2 float-end" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={()=>this.addClick()}> Add Department </button> <table className="table table-striped"> <thead> <tr> <th> <div className="d-flex flex-row"> <input className="form-control m-2" onChange={this.changeDepartmentIdFilter} placeholder="Filter"/> <button type="button" className="btn btn-light" onClick={()=>this.sortResult('DepartmentId',true)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-down-square-fill" viewBox="0 0 16 16"> <path d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"/> </svg> </button> <button type="button" className="btn btn-light" onClick={()=>this.sortResult('DepartmentId',false)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-up-square-fill" viewBox="0 0 16 16"> <path d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"/> </svg> </button> </div> DepartmentId </th> <th> <div className="d-flex flex-row"> <input className="form-control m-2" onChange={this.changeDepartmentNameFilter} placeholder="Filter"/> <button type="button" className="btn btn-light" onClick={()=>this.sortResult('DepartmentName',true)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-down-square-fill" viewBox="0 0 16 16"> <path d="M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5a.5.5 0 0 1 1 0z"/> </svg> </button> <button type="button" className="btn btn-light" onClick={()=>this.sortResult('DepartmentName',false)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-arrow-up-square-fill" viewBox="0 0 16 16"> <path d="M2 16a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2zm6.5-4.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 1 0z"/> </svg> </button> </div> DepartmentName </th> <th> Options </th> </tr> </thead> <tbody> {departments.map(dep=> <tr key={dep.DepartmentId}> <td>{dep.DepartmentId}</td> <td>{dep.DepartmentName}</td> <td> <button type="button" className="btn btn-light mr-1" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={()=>this.editClick(dep)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-pencil-square" viewBox="0 0 16 16"> <path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/> <path fillRule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/> </svg> </button> <button type="button" className="btn btn-light mr-1" onClick={()=>this.deleteClick(dep.DepartmentId)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-trash-fill" viewBox="0 0 16 16"> <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"/> </svg> </button> </td> </tr> )} </tbody> </table> <div className="modal fade" id="exampleModal" tabIndex="-1" aria-hidden="true"> <div className="modal-dialog modal-lg modal-dialog-centered"> <div className="modal-content"> <div className="modal-header"> <h5 className="modal-title">{modalTitle}</h5> <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close" ></button> </div> <div className="modal-body"> <div className="input-group mb-3"> <span className="input-group-text">DepartmentName</span> <input type="text" className="form-control" value={DepartmentName} onChange={this.changeDepartmentName}/> </div> {DepartmentId==0? <button type="button" className="btn btn-primary float-start" onClick={()=>this.createClick()} >Create</button> :null} {DepartmentId!=0? <button type="button" className="btn btn-primary float-start" onClick={()=>this.updateClick()} >Update</button> :null} </div> </div> </div> </div> </div> ) } }
import React,{Component} from 'react'; import {variables} from './Variables.js'; export class Employee extends Component{ constructor(props){ super(props); this.state={ departments:[], employees:[], modalTitle:"", EmployeeId:0, EmployeeName:"", Department:"", DateOfJoining:"", PhotoFileName:"anonymous.png", PhotoPath:variables.PHOTO_URL } } refreshList(){ fetch(variables.API_URL+'employee') .then(response=>response.json()) .then(data=>{ this.setState({employees:data}); }); fetch(variables.API_URL+'department') .then(response=>response.json()) .then(data=>{ this.setState({departments:data}); }); } componentDidMount(){ this.refreshList(); } changeEmployeeName =(e)=>{ this.setState({EmployeeName:e.target.value}); } changeDepartment =(e)=>{ this.setState({Department:e.target.value}); } changeDateOfJoining =(e)=>{ this.setState({DateOfJoining:e.target.value}); } addClick(){ this.setState({ modalTitle:"Add Employee", EmployeeId:0, EmployeeName:"", Department:"", DateOfJoining:"", PhotoFileName:"anonymous.png" }); } editClick(emp){ this.setState({ modalTitle:"Edit Employee", EmployeeId:emp.EmployeeId, EmployeeName:emp.EmployeeName, Department:emp.Department, DateOfJoining:emp.DateOfJoining, PhotoFileName:emp.PhotoFileName }); } createClick(){ fetch(variables.API_URL+'employee',{ method:'POST', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' }, body:JSON.stringify({ EmployeeName:this.state.EmployeeName, Department:this.state.Department, DateOfJoining:this.state.DateOfJoining, PhotoFileName:this.state.PhotoFileName }) }) .then(res=>res.json()) .then((result)=>{ alert(result); this.refreshList(); },(error)=>{ alert('Failed'); }) } updateClick(){ fetch(variables.API_URL+'employee',{ method:'PUT', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' }, body:JSON.stringify({ EmployeeId:this.state.EmployeeId, EmployeeName:this.state.EmployeeName, Department:this.state.Department, DateOfJoining:this.state.DateOfJoining, PhotoFileName:this.state.PhotoFileName }) }) .then(res=>res.json()) .then((result)=>{ alert(result); this.refreshList(); },(error)=>{ alert('Failed'); }) } deleteClick(id){ if(window.confirm('Are you sure?')){ fetch(variables.API_URL+'employee/'+id,{ method:'DELETE', headers:{ 'Accept':'application/json', 'Content-Type':'application/json' } }) .then(res=>res.json()) .then((result)=>{ alert(result); this.refreshList(); },(error)=>{ alert('Failed'); }) } } imageUpload=(e)=>{ e.preventDefault(); const formData=new FormData(); formData.append("file",e.target.files[0],e.target.files[0].name); fetch(variables.API_URL+'employee/savefile',{ method:'POST', body:formData }) .then(res=>res.json()) .then(data=>{ this.setState({PhotoFileName:data}); }) } render(){ const { departments, employees, modalTitle, EmployeeId, EmployeeName, Department, DateOfJoining, PhotoPath, PhotoFileName }=this.state; return( <div> <button type="button" className="btn btn-primary m-2 float-end" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={()=>this.addClick()}> Add Employee </button> <table className="table table-striped"> <thead> <tr> <th> EmployeeId </th> <th> EmployeeName </th> <th> Department </th> <th> DOJ </th> <th> Options </th> </tr> </thead> <tbody> {employees.map(emp=> <tr key={emp.EmployeeId}> <td>{emp.EmployeeId}</td> <td>{emp.EmployeeName}</td> <td>{emp.Department}</td> <td>{emp.DateOfJoining}</td> <td> <button type="button" className="btn btn-light mr-1" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={()=>this.editClick(emp)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-pencil-square" viewBox="0 0 16 16"> <path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/> <path fillRule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/> </svg> </button> <button type="button" className="btn btn-light mr-1" onClick={()=>this.deleteClick(emp.EmployeeId)}> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" className="bi bi-trash-fill" viewBox="0 0 16 16"> <path d="M2.5 1a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1H3v9a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V4h.5a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H10a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1H2.5zm3 4a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5zM8 5a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7A.5.5 0 0 1 8 5zm3 .5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 1 0z"/> </svg> </button> </td> </tr> )} </tbody> </table> <div className="modal fade" id="exampleModal" tabIndex="-1" aria-hidden="true"> <div className="modal-dialog modal-lg modal-dialog-centered"> <div className="modal-content"> <div className="modal-header"> <h5 className="modal-title">{modalTitle}</h5> <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close" ></button> </div> <div className="modal-body"> <div className="d-flex flex-row bd-highlight mb-3"> <div className="p-2 w-50 bd-highlight"> <div className="input-group mb-3"> <span className="input-group-text">Emp Name</span> <input type="text" className="form-control" value={EmployeeName} onChange={this.changeEmployeeName}/> </div> <div className="input-group mb-3"> <span className="input-group-text">Department</span> <select className="form-select" onChange={this.changeDepartment} value={Department}> {departments.map(dep=><option key={dep.DepartmentId}> {dep.DepartmentName} </option>)} </select> </div> <div className="input-group mb-3"> <span className="input-group-text">DOJ</span> <input type="date" className="form-control" value={DateOfJoining} onChange={this.changeDateOfJoining}/> </div> </div> <div className="p-2 w-50 bd-highlight"> <img width="250px" height="250px" src={PhotoPath+PhotoFileName}/> <input className="m-2" type="file" onChange={this.imageUpload}/> </div> </div> {EmployeeId==0? <button type="button" className="btn btn-primary float-start" onClick={()=>this.createClick()} >Create</button> :null} {EmployeeId!=0? <button type="button" className="btn btn-primary float-start" onClick={()=>this.updateClick()} >Update</button> :null} </div> </div> </div> </div> </div> ) } }
This comment has been removed by the author.
ReplyDeleteI got error 404 in image retrieval from PHOTO_URL:"http://127.0.0.1:8000/Photos/", this is my python django API.
ReplyDeleteArt Of Engineer: React Js + Python Django + Sqlite >>>>> Download Now
ReplyDelete>>>>> Download Full
Art Of Engineer: React Js + Python Django + Sqlite >>>>> Download LINK
>>>>> Download Now
Art Of Engineer: React Js + Python Django + Sqlite >>>>> Download Full
>>>>> Download LINK v0
hi please help !! "Uncaught TypeError: Cannot read properties of undefined (reading 'backdrop')"
ReplyDeletethanks
ReplyDelete