To create a simple CRUD (Create, Read, Update, Delete) application using React.js for the frontend and Django as the backend
To create a simple CRUD (Create, Read, Update, Delete) application using React.js for the frontend and Django as the backend, we’ll break it down into two parts:
Backend: Django API (using Django Rest Framework)
1. Install Django & Django Rest Framework & Install django-cors-headers :
First, you need to set up your Django project if you haven't already.
2. Create a new Django project:
3. Create a Django app:
4. Configure INSTALLED_APPS in school_management/settings.py:
5. Define the Student model:
In students/models.py, define the model for Student Enquiry and Admission records.
6. Create a serializer for the model:
In students/serializers.py, create a serializer for the Student model:
7. Create views for CRUD operations:
In students/views.py, create views using Django Rest Framework's viewsets.
8. Register the ViewSet in urls.py:
In students/urls.py, set up the URL routing for the API.
9. Add the URLs to the main project:
In school_management/urls.py, include the students app URLs.
10. Migrate the database:
11. Run the Django server:
Now the Django API is ready to handle CRUD operations on the student records.
Frontend: React.js
1. Set up a React project:
If you don’t already have a React project, create one using create-react-app.
2. Install Axios to make API requests:
3. Create a component to display, add, update, and delete students:
Here’s a simplified example to manage student records.
src/StudentApp.js:
4. Set up the main App.js file:
In src/App.js, render the StudentApp component.
5. Run the React application:
How It Works:
-
Backend (Django): The Django API handles all the CRUD operations for the student records.
-
Frontend (React): The React app communicates with the Django API to display, add, update, and delete student records.
-
The
useEffecthook fetches student records when the component mounts. -
The form handles adding and updating student records.
-
The delete button removes a student record.
Here's a line-by-line explanation of what each above React piece does:-
const [students, setStudents] = useState([]);
const [formData, setFormData] = useState({
first_name: "",
last_name: "",
email: "",
phone: "",
admission_status: false
});
const [editStudent, setEditStudent] = useState(null);
This React code snippet uses the useState hook to manage local component state. Here's a line-by-line
explanation of what each piece does:
📌
1. const [students, setStudents] =
useState([]);
- Purpose:
Manages the list of all students.
- Initial value:
An empty array [].
- Usage:
- students
stores the list of student objects (like from an API or database).
- setStudents
is a function used to update that list.
Example:
setStudents([
{ id: 1, first_name: "Alice", last_name:
"Smith" },
{ id: 2, first_name: "Bob", last_name:
"Jones" }
]);
📌
2. const [formData, setFormData] =
useState({ ... });
- Purpose:
Manages the form input values for creating or editing a student.
- Initial value:
An object with empty strings or default values.
{
first_name: "",
last_name: "",
email: "",
phone: "",
admission_status: false
}
- Usage:
- formData
holds the current values of the form fields.
- setFormData
updates one or more fields when the user types.
Example:
setFormData({
...formData, first_name: "John" });
📌
3. const [editStudent, setEditStudent]
= useState(null);
- Purpose:
Tracks which student is currently being edited.
- Initial value:
null
(meaning no student is selected for editing).
- Usage:
- When editing starts, set it to the student object
you're editing.
- When editing ends or is canceled, set it back to null.
Example:
setEditStudent({
id: 1, first_name: "Alice", ... });
✅
Summary
This code sets up three pieces of
state for a student management UI:
- students:
all student records
- formData:
form values for adding/editing
- editStudent:
the currently selected student for editing
This is a common pattern in React
apps involving CRUD operations (Create, Read, Update, Delete).
Let me know if you'd like an example
form or how this would connect to a Django backend.
This
code defines an asynchronous
function called fetchStudents that retrieves
all student records from an API and updates the React state. Let's break it
down step by step:
🧠 Code:
//
Fetch all students
const fetchStudents = async () => {
const response = await axios.get(API_URL);
setStudents(response.data);
};
🔍 Line-by-Line Explanation
const fetchStudents = async () => {
... };
- Defines a function named
fetchStudentsthat is asynchronous. - This means it can use
awaitto wait for asynchronous operations (like HTTP requests).
const response = await
axios.get(API_URL);
- Uses
axiosto send a GET request to theAPI_URL(a variable likely containing the backend endpoint URL). - The function waits (
await) until the request is complete and stores the response in theresponsevariable.
setStudents(response.data);
- After the data is fetched from the API, it
updates the
studentsstate (previously declared usinguseState([])). response.datacontains the list of students returned from the backend (usually as JSON).
📌 What This Code Does in Practice:
- It talks to your Django backend (or any
API).
- Fetches student records like this:
[ { "id": 1, "first_name": "Alice", "last_name": "Smith", ... }, { "id": 2, "first_name": "Bob", "last_name": "Jones", ... }]
- Then stores this list in the component’s
studentsstate, so it can be displayed in the UI.
✅ Summary:
This function is used to load all students from the server
and store them in React state, typically to display them in a table or list.
This
code defines a function called handleSubmit that is used
to submit a form
in a React app. The form is used either to add a new student or update an existing student.
Let's break it down line by line for clarity.
🧠 Full Code:
// Add
or update student
const handleSubmit = async (e) => {
e.preventDefault();
if (editStudent) {
await axios.put(`${API_URL}${editStudent.id}/`, formData);
} else {
await axios.post(API_URL, formData);
}
fetchStudents();
setFormData({
first_name: "",
last_name: "",
email: "",
phone: "",
admission_status: false
});
setEditStudent(null);
};
🔍 Line-by-Line Explanation
const handleSubmit = async (e) => {
Defines an asynchronous function to handle form
submission.
e.preventDefault();
Prevents the browser’s default form submission
behavior (like refreshing the page).
if (editStudent) {
Checks whether the form is in edit mode. If
editStudent
is not null, the user is editing an existing student.
await axios.put(${API_URL}${editStudent.id}/,
formData);
- Sends a PUT request to update the
existing student.
- Example URL:
http://localhost:8000/api/students/5/ formDatacontains the updated student information.
} else { await axios.post(API_URL,
formData); }
If not in edit mode:
- Sends a POST request to add a new
student to the database.
- Uses the same
formData, but creates a new student.
fetchStudents();
After adding or updating, it refreshes the list of
students by calling the fetchStudents function
(which you defined earlier).
setFormData({ ... });
- Clears the form fields by
resetting
formDatato empty/default values. - Prepares the form for a new entry.
setEditStudent(null);
- Clears the
editStudentstate. - Exits edit mode so the next form submission
will add a new student.
✅ Summary:
This function does two things:
- Adds a new student (if not
editing).
- Updates an existing
student (if in edit mode).
After either operation, it:
- Refreshes the student list,
- Clears the form,
- And exits edit mode.
This
code defines a function called handleDelete that deletes a student
by making a request to your backend API. Let’s break it down:
🧠 Code:
//
Delete student
const handleDelete = async (id) => {
await axios.delete(`${API_URL}${id}/`);
fetchStudents();
};
🔍 Line-by-Line Explanation:
const handleDelete = async (id) => {
- This is an asynchronous function that
takes a single argument:
id, the unique ID of the student to delete.
await axios.delete(\${API_URL}${id}/`);`
- Sends a DELETE request to the
backend API.
${API_URL}${id}/builds a URL like:
http://localhost:8000/api/students/5/
(assumingAPI_URL = "http://localhost:8000/api/students/")- This tells the backend to delete the student
with that ID.
fetchStudents();
- After deleting the student, this function is
called to refresh the list of students.
- This ensures the UI updates and removes the
deleted student from the visible list.
✅ Summary:
This function:
- Deletes a student record from the backend
using their ID.
- Then updates the UI by fetching the latest
list of students.
🧩 Example Use in a Button:
<button onClick={() => handleDelete(student.id)}>Delete</button>
This would delete the student when the button is
clicked.
This
code defines the handleEdit function, which is used to enable edit mode
for a student in your React app. Let’s break it down:
🧠 Code:
// Edit
student
const handleEdit = (student) => {
setFormData(student);
setEditStudent(student);
};
🔍 Line-by-Line Explanation:
const handleEdit = (student) => {
- Defines a function called
handleEditthat takes astudentobject as its parameter. - This
studentis the one the user wants to edit (typically clicked on from a list or table).
setFormData(student);
- Updates the
formDatastate to pre-fill the form with the student's current details. - This allows the form inputs (like name, email,
etc.) to show the existing values for easy editing.
setEditStudent(student);
- Sets the
editStudentstate to the selected student. - This signals that the form is now in edit
mode.
- Later, when the form is submitted, the code
will know to send a PUT request instead of POST.
✅ Summary:
This function is used when a user clicks “Edit”
on a student:
- Loads the student data into the form
so the user can modify it.
- Marks the form as being in edit mode,
so the correct backend operation (update, not add) is performed on submit.
🧩 Example Usage:
<button onClick={() => handleEdit(student)}>Edit</button>
This would populate the form with that student's
details when clicked.
This
line of code uses React’s useEffect hook to automatically fetch all
students when the component loads (i.e. on mount).
🧠 Code:
useEffect(() => {
fetchStudents();
}, []);
🔍 Line-by-Line Explanation:
useEffect(() => { ... }, []);
useEffectis a React hook that lets you run code after the component renders.- The
[](empty array) as the second argument is called the dependency array. - It means: run this effect only once,
when the component is first mounted (like
componentDidMountin class components).
fetchStudents();
- Calls the
fetchStudentsfunction, which (as explained earlier) sends a GET request to your backend and sets thestudentsstate with the data.
✅ Summary:
This ensures the student list is automatically
loaded when the component is first displayed on the page.
This
is the JSX (render) part of a React
component for managing student enquiries and admissions. It
contains a form for
adding/updating students and a list to display them with
edit/delete options.
Let’s walk through what it does step by step:
return (
<div>
<h1>Student Enquiry & Admission
Management</h1>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="First Name"
value={formData.first_name}
onChange={(e) => setFormData({ ...formData, first_name: e.target.value })}
/>
<input
type="text"
placeholder="Last Name"
value={formData.last_name}
onChange={(e) => setFormData({ ...formData, last_name: e.target.value })}
/>
<input
type="email"
placeholder="Email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
/>
<input
type="text"
placeholder="Phone"
value={formData.phone}
onChange={(e) => setFormData({ ...formData, phone: e.target.value })}
/>
<label>
Admission
Status:
<input
type="checkbox"
checked={formData.admission_status}
onChange={() => setFormData({ ...formData, admission_status: !formData.admission_status })}
/>
</label>
<button type="submit">{editStudent ? "Update" : "Add"} Student</button>
</form>
<h2>Student List</h2>
<ul>
{students.map((student) => (
<li key={student.id}>
<span>{student.first_name} {student.last_name} ({student.email})</span>
<button onClick={() => handleEdit(student)}>Edit</button>
<button onClick={() => handleDelete(student.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
This
is what React will render to the screen.
🧾 1.
Main Heading
<h1>Student Enquiry & Admission Management</h1>
- A title at the top of the page.
🧾 2.
Student Form
<form onSubmit={handleSubmit}>
- A form that either adds a new student or updates
an existing one.
handleSubmithandles form submission logic (eitherPOSTorPUTdepending oneditStudent).
🔹
Form Inputs:
Each input is bound to the formData state via value
and updated on change:
<input type="text" placeholder="First Name" value={formData.first_name} onChange={...} />
So as users type, the form state updates
immediately.
🔹
Checkbox for admission status:
<input type="checkbox" checked={formData.admission_status} onChange={...} />
- Toggled using
!formData.admission_status.
🔹
Submit Button:
<button type="submit">{editStudent ? "Update" : "Add"} Student</button>
- Dynamically changes label based on whether a
student is being edited.
📋 3. Student List
<ul> {students.map((student) => ( <li key={student.id}> ... </li> ))}</ul>
- Loops over the
studentsarray. - Displays each student's name and email.
- Provides
EditandDeletebuttons:
🛠
Edit Button:
<button onClick={() => handleEdit(student)}>Edit</button>
- Calls
handleEdit, which loads that student's data into the form.
❌ Delete
Button:
<button onClick={() => handleDelete(student.id)}>Delete</button>
- Deletes the student by their ID.
✅ Summary
This JSX renders:
|
Feature |
What it does |
|
🧾
Form |
Add or edit a student using |
|
📋
Student List |
Lists students with buttons to edit or delete each one. |
|
♻
Dynamic Text |
Button label shows "Add" or "Update"
depending on |
In students/models.py, define the model for Student Enquiry and Admission records.
🧩 Code:
-
Imports Django’s model tools. Everything in a model must inherit from
models.Model.
🎓 class Student(models.Model):
-
Defines a model class named
Student. -
Each attribute inside it becomes a field in the corresponding database table.
🔢 Field-by-Field Explanation
✅ first_name = models.CharField(max_length=100)
-
A short text field for the student's first name.
-
max_length=100: Limits the length in the database and form.
✅ last_name = models.CharField(max_length=100)
-
Same as
first_name, but for the last name.
✅ email = models.EmailField(unique=True)
-
Stores the student's email address.
-
EmailField: Adds email format validation. -
unique=True: Ensures no two students have the same email.
✅ phone = models.CharField(max_length=15)
-
Stores a phone number as a string (not an integer because of possible special characters like
+,-, etc.)
✅ enquiry_date = models.DateTimeField(auto_now_add=True)
-
Automatically sets the current date and time when a student record is created.
-
Not editable manually unless specified.
✅ admission_status = models.BooleanField(default=False)
-
A True/False field.
-
Default is
False, meaning the student has not been admitted yet.
🔁 def __str__(self):
-
Defines the string representation of a student object.
-
This is what will show in the Django admin or shell (e.g.,
Student: John Doeinstead ofStudent: <Student object>).
🧱 What This Model Does in the Database:
Django will create a table like:
| id | first_name | last_name | phone | enquiry_date | admission_status | |
|---|---|---|---|---|---|---|
| 1 | John | Doe | john@email.com | 1234567890 | 2025-05-15 12:00 | False |
✅ Summary:
This model defines a student enquiry and admission record, with fields for name, contact details, enquiry date, and whether they were admitted. It supports create, read, update, delete (CRUD) operations via Django’s ORM.
In students/serializers.py, create a serializer for the Student model:
🧩 Code:
-
serializersis imported from Django REST Framework, which provides tools to convert models and other data types to and from JSON. -
The
Studentmodel is imported to define which data structure the serializer will handle.
🎓 class StudentSerializer(serializers.ModelSerializer):
-
StudentSerializeris a subclass ofserializers.ModelSerializer, which is a shortcut that automatically generates a serializer for a model. -
It works closely with Django’s ORM, meaning you don’t have to manually define each field — DRF will handle that for you based on the model.
🔑 class Meta:
-
The
Metaclass is used to provide configuration options for the serializer. -
model = Student: This tells the serializer to work with theStudentmodel. -
fields = [...]: A list of fields that should be included in the serialized output. These fields will be converted to and from JSON when working with the API.-
id: The unique identifier (usually auto-generated by Django). -
first_name,last_name: The student’s name fields. -
email,phone: The student’s contact information. -
enquiry_date: The timestamp for when the student made an enquiry. -
admission_status: The status of the student’s admission (True or False).
-
✅ What This Serializer Does:
-
Converts
Studentmodel instances into JSON data that can be returned from an API endpoint. -
Validates incoming data when creating or updating
Studentinstances. -
This serializer can be used in views (e.g., with Django REST Framework's
APIVieworModelViewSet) to automatically handle CRUD operations (Create, Read, Update, Delete) onStudentdata.
🧩 Example of Use in Views:
For example, this serializer could be used in a Django REST API view to serialize Student objects into JSON format.
-
This will create an API endpoint for handling
GET,POST,PUT, andDELETErequests forStudentdata, using theStudentSerializerto convert between Python objects and JSON.
✅ Summary:
-
StudentSerializerconvertsStudentmodel data to and from JSON for use in an API. -
It's connected to the
Studentmodel, and only the specified fields are included. -
This serializer is typically used in a viewset to enable CRUD operations through a REST API.
In students/views.py, create views using Django Rest Framework's viewsets.
This code defines a viewset for handling the Student model using Django REST Framework (DRF). The StudentViewSet class provides the logic to interact with the Student model and automatically handles the CRUD (Create, Read, Update, Delete) operations for student records.
Let’s break it down step by step:
🧩 Code:
🔍 Line-by-Line Explanation:
from rest_framework import viewsets
-
Imports
viewsetsfrom Django REST Framework. -
A viewset is a class that provides the CRUD functionality for a model. It simplifies the creation of views by automatically providing methods for handling HTTP requests (like
GET,POST,PUT,DELETE).
from .models import Student
-
Imports the
Studentmodel from the same directory (models.py). This is the model you want to expose via the API.
from .serializers import StudentSerializer
-
Imports the
StudentSerializerfrom theserializers.pyfile. The serializer is responsible for converting model instances into JSON format and vice versa.
class StudentViewSet(viewsets.ModelViewSet):
-
This creates a viewset class called
StudentViewSet. -
ModelViewSetis a DRF class that provides a full set of default actions (such aslist,create,retrieve,update,destroy) for handling model data.-
ModelViewSetautomatically connects your model with HTTP methods to create, retrieve, update, or delete records.
-
queryset = Student.objects.all()
-
querysetdefines the list of objects that the viewset will operate on. -
Student.objects.all()retrieves all records from theStudentmodel in the database. -
This allows the
StudentViewSetto manage all students in the database.
serializer_class = StudentSerializer
-
serializer_classspecifies the serializer that will be used to transform model instances into JSON format and validate incoming data. -
Here,
StudentSerializerwill be used to handle the serialization of theStudentmodel.
✅ Summary of What This Code Does:
-
CRUD Operations: The
StudentViewSetclass automatically provides the following actions:-
list: Retrieve and return a list of all students (GET). -
create: Add a new student (POST). -
retrieve: Retrieve a specific student by ID (GETwith a parameter). -
update: Update an existing student's data (PUT). -
partial_update: Partially update a student's data (PATCH). -
destroy: Delete a student (DELETE).
-
-
Automatic URL Routing: If you're using Django REST Framework's router, this viewset automatically gets wired to URLs for CRUD operations, so you don't have to manually define those routes
In students/urls.py, set up the URL routing for the API.
This code sets up the URLs for your Django REST API, which allows users to interact with the Student model via HTTP requests. It uses Django REST Framework’s DefaultRouter to automatically generate routes for CRUD operations. Let’s break it down line by line:
🧩 Code:
🔍 Line-by-Line Explanation:
from django.urls import path, include
-
path: Used to define individual URL patterns (routes). -
include: Used to reference other URL configurations (in this case, therouter.urls).
from rest_framework.routers import DefaultRouter
-
DefaultRouter: This is a special class from Django REST Framework that automatically generates URL patterns for your viewsets.-
It generates the URLs for common actions like
list,create,retrieve,update, anddelete.
-
from .views import StudentViewSet
-
StudentViewSetis imported from theviews.pyfile. -
This viewset is responsible for handling CRUD operations for the
Studentmodel (viaStudentSerializer).
router = DefaultRouter()
-
Creates an instance of
DefaultRouter. -
This router will automatically generate routes for your
StudentViewSet.
router.register(r'students', StudentViewSet)
-
register()method links theStudentViewSetto thestudentsroute.-
r'students': This defines the base URL path for this viewset. It means that all the actions forStudentViewSetwill be accessible via/students/. -
StudentViewSet: The viewset class that defines how theStudentmodel will be handled.
-
urlpatterns = [ path('api/', include(router.urls)), ]
-
urlpatternsis a list of all URL patterns in your app. -
path('api/', include(router.urls)): This includes all the generated URLs from theDefaultRouterunder theapi/path.-
router.urlswill automatically generate the following routes:-
/api/students/: To retrieve the list of students or create a new student (viaGETandPOST). -
/api/students/{id}/: To retrieve, update, or delete a specific student by ID (viaGET,PUT,PATCH, andDELETE).
-
-
So, the API URLs will look like this:
-
GET /api/students/: List all students. -
POST /api/students/: Add a new student. -
GET /api/students/{id}/: Retrieve a specific student by their ID. -
PUT /api/students/{id}/: Update a student's details. -
PATCH /api/students/{id}/: Partially update a student's details. -
DELETE /api/students/{id}/: Delete a student.
-
-
✅ Summary:
This code sets up the API URLs for your Student model, using Django REST Framework’s router to automatically generate routes for common CRUD operations (GET, POST, PUT, PATCH, DELETE).
-
DefaultRouter()generates the necessary URLs. -
register('students', StudentViewSet)connects the URL/students/to theStudentViewSet. -
include(router.urls)includes the generated URL patterns under the/api/prefix.
With this in place, you now have a fully functioning REST API for managing student data!
In school_management/urls.py, include the students app URLs.
....
....
The code you've shown correctly includes the URLs from the students app into your main project's urls.py file, which is typically located at:
school_management/urls.py
✅ Final Code (Correct):
🔍 What This Does:
-
admin/: Points to the Django admin site. -
''(empty string): Means that any base-level URL (like/api/students/) will be routed through thestudents.urlsmodule.-
Inside
students/urls.py, you already have: -
So the full URL for your student API becomes:
-
✅ Resulting API Endpoints:
Once everything is wired up and the server is running, these URLs become active:
| HTTP Method | URL | Action |
|---|---|---|
| GET | /api/students/ | List all students |
| POST | /api/students/ | Add a new student |
| GET | /api/students/<id>/ | Get details of a student |
| PUT/PATCH | /api/students/<id>/ | Update a student |
| DELETE | /api/students/<id>/ | Delete a student |
Comments
Post a Comment