Lesson 54 of 60 – Django CRUD Project
90%

Django CRUD Project

CRUD stands for Create, Read, Update, and Delete. These four operations are the foundation of many database-driven web applications.

In this lesson, we will understand how to build a simple Django CRUD project using a Student model. The project will allow an administrator or user to add students, view students, edit student information, and delete students.

Note: CRUD applications are commonly used for student management, employee management, product management, customer management, and many other database applications.

1. What is CRUD?

CRUD represents four basic database operations:

  • Create – Add a new record.
  • Read – Display existing records.
  • Update – Modify an existing record.
  • Delete – Remove a record.
Create → Add Student
Read   → View Students
Update → Edit Student
Delete → Delete Student

2. CRUD Project Example

Suppose we are building a student management system.

Each student may have:

  • Name
  • Email
  • Course
  • Age

Our CRUD system will allow us to manage these records from a web interface.

3. Create a Django App

First, create an application for the CRUD functionality.

python manage.py startapp students

Then add the application to INSTALLED_APPS in settings.py.

INSTALLED_APPS = [
    ...
    "students",
]

4. Create the Student Model

Create the Student model in students/models.py.

from django.db import models

class Student(models.Model):

    name = models.CharField(
        max_length=100
    )

    email = models.EmailField()

    course = models.CharField(
        max_length=100
    )

    age = models.IntegerField()

    def __str__(self):
        return self.name

5. Create Database Tables

After creating or changing a model, create and apply migrations.

python manage.py makemigrations

python manage.py migrate

The migration system creates the required database table.

6. Create a ModelForm

A ModelForm can automatically create form fields from the Student model.

Create students/forms.py:

from django import forms
from .models import Student

class StudentForm(forms.ModelForm):

    class Meta:

        model = Student

        fields = [
            "name",
            "email",
            "course",
            "age"
        ]

7. Create Student View

The create view displays the form and saves a new student after a valid POST request.

from django.shortcuts import render, redirect
from .forms import StudentForm

def student_create(request):

    if request.method == "POST":

        form = StudentForm(
            request.POST
        )

        if form.is_valid():

            form.save()

            return redirect(
                "student_list"
            )

    else:

        form = StudentForm()

    return render(
        request,
        "students/student_form.html",
        {
            "form": form
        }
    )

8. Create Student Template

Create a template for the student form.

<h2>Add Student</h2>

<form method="post">

    {% csrf_token %}

    {{ form.as_p }}

    <button type="submit">
        Save Student
    </button>

</form>

The csrf_token protects the POST form against CSRF attacks.

9. Read Student Records

The read operation retrieves records from the database.

from .models import Student

def student_list(request):

    students = Student.objects.all()

    return render(
        request,
        "students/student_list.html",
        {
            "students": students
        }
    )

10. Display Students in Template

<h2>Student List</h2>

<table>

    <tr>
        <th>Name</th>
        <th>Email</th>
        <th>Course</th>
        <th>Age</th>
    </tr>

    {% for student in students %}

    <tr>

        <td>
            {{ student.name }}
        </td>

        <td>
            {{ student.email }}
        </td>

        <td>
            {{ student.course }}
        </td>

        <td>
            {{ student.age }}
        </td>

    </tr>

    {% endfor %}

</table>

11. Update Student Records

The update operation retrieves an existing student and passes it to the ModelForm using the instance argument.

from django.shortcuts import get_object_or_404

def student_update(request, id):

    student = get_object_or_404(
        Student,
        id=id
    )

    if request.method == "POST":

        form = StudentForm(
            request.POST,
            instance=student
        )

        if form.is_valid():

            form.save()

            return redirect(
                "student_list"
            )

    else:

        form = StudentForm(
            instance=student
        )

    return render(
        request,
        "students/student_form.html",
        {
            "form": form
        }
    )

12. Delete Student Records

The delete operation removes a record from the database.

def student_delete(request, id):

    student = get_object_or_404(
        Student,
        id=id
    )

    if request.method == "POST":

        student.delete()

        return redirect(
            "student_list"
        )

    return render(
        request,
        "students/student_confirm_delete.html",
        {
            "student": student
        }
    )

13. Why Use get_object_or_404?

get_object_or_404() retrieves an object or returns a 404 response when the requested object does not exist.

student = get_object_or_404(
    Student,
    id=id
)

This is safer and cleaner than assuming that the requested record always exists.

14. Create URL Patterns

Create students/urls.py.

from django.urls import path
from . import views

urlpatterns = [

    path(
        "",
        views.student_list,
        name="student_list"
    ),

    path(
        "add/",
        views.student_create,
        name="student_create"
    ),

    path(
        "edit/<int:id>/",
        views.student_update,
        name="student_update"
    ),

    path(
        "delete/<int:id>/",
        views.student_delete,
        name="student_delete"
    ),

]

15. Include App URLs

Include the student app URLs in the main project's urls.py.

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

urlpatterns = [

    path(
        "admin/",
        admin.site.urls
    ),

    path(
        "students/",
        include("students.urls")
    ),

]

Now the student list can be accessed through:

/students/

16. Add Link to Create Student

The student list page can contain a link to the create page.

<a href="{% url 'student_create' %}">
    Add Student
</a>

Using the URL name is better than hard-coding the complete URL.

17. Add Edit Link

Each student can have an Edit link.

<a href="{% url 'student_update' student.id %}">
    Edit
</a>

The student's ID is passed to the URL parameter.

18. Add Delete Form

A POST form can be used for deletion.

<form
    method="post"
    action="{% url 'student_delete' student.id %}"
>

    {% csrf_token %}

    <button type="submit">
        Delete
    </button>

</form>

Using POST for destructive operations helps avoid deleting records through simple GET requests.

19. Delete Confirmation Page

<h2>
Delete Student
</h2>

<p>
Are you sure you want to delete
{{ student.name }}?
</p>

<form method="post">

    {% csrf_token %}

    <button type="submit">
        Yes, Delete
    </button>

</form>

<a href="{% url 'student_list' %}">
    Cancel
</a>

The user gets a chance to cancel before the record is deleted.

20. Student Template Structure

A simple CRUD project can use the following template structure:

students/
└── templates/
    └── students/
        ├── student_list.html
        ├── student_form.html
        └── student_confirm_delete.html

Keeping related templates inside the app makes the project easier to organize.

21. CRUD Project Structure

myproject/
│
├── manage.py
│
├── myproject/
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   └── wsgi.py
│
└── students/
    ├── migrations/
    ├── templates/
    │   └── students/
    │       ├── student_list.html
    │       ├── student_form.html
    │       └── student_confirm_delete.html
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── forms.py
    ├── models.py
    ├── urls.py
    ├── views.py
    └── tests.py

22. Using Bootstrap in CRUD

Bootstrap can be used to make the CRUD pages easier to use.

<div class="container mt-4">

    <h2>Student List</h2>

    <a
        href="{% url 'student_create' %}"
        class="btn btn-primary"
    >
        Add Student
    </a>

</div>

Bootstrap classes can also be applied to forms, tables, buttons, alerts, and navigation.

23. CRUD with Search

A CRUD application can be combined with the Django search system learned in the previous lesson.

query = request.GET.get(
    "q",
    ""
).strip()

students = Student.objects.all()

if query:

    students = students.filter(
        name__icontains=query
    )

This allows users to find a record before editing or deleting it.

24. CRUD with Pagination

When the database contains many records, pagination can be added to the student list.

from django.core.paginator import Paginator

paginator = Paginator(
    students,
    10
)

page_number = request.GET.get(
    "page"
)

page_obj = paginator.get_page(
    page_number
)

The template can then display page_obj instead of the complete QuerySet.

25. CRUD with Messages

Django's messages framework can provide feedback after CRUD operations.

from django.contrib import messages

form.save()

messages.success(
    request,
    "Student added successfully."
)

return redirect(
    "student_list"
)

Similar messages can be created after updating or deleting records.

26. CRUD Operation Flow

Add Student
     ↓
Display Form
     ↓
Submit POST Request
     ↓
Validate Form
     ↓
Save Record
     ↓
Redirect to List


View Students
     ↓
Query Database
     ↓
Display Records


Edit Student
     ↓
Get Existing Record
     ↓
Load ModelForm
     ↓
Validate Form
     ↓
Save Changes
     ↓
Redirect to List


Delete Student
     ↓
Get Existing Record
     ↓
Confirm Delete
     ↓
Delete Record
     ↓
Redirect to List

27. Common CRUD Mistakes

  • Forgetting to add the app to INSTALLED_APPS.
  • Forgetting to run migrations.
  • Using the wrong model name.
  • Forgetting csrf_token in POST forms.
  • Using the wrong URL name.
  • Forgetting to pass instance while updating.
  • Deleting records through an unsafe GET request.
  • Not handling records that do not exist.
  • Forgetting to import get_object_or_404.
  • Forgetting to include app URLs in the project URLs.

28. Complete CRUD View Example

from django.shortcuts import (
    render,
    redirect,
    get_object_or_404
)

from django.contrib import messages

from .models import Student
from .forms import StudentForm


def student_list(request):

    students = Student.objects.all()

    return render(
        request,
        "students/student_list.html",
        {
            "students": students
        }
    )


def student_create(request):

    if request.method == "POST":

        form = StudentForm(
            request.POST
        )

        if form.is_valid():

            form.save()

            messages.success(
                request,
                "Student added successfully."
            )

            return redirect(
                "student_list"
            )

    else:

        form = StudentForm()

    return render(
        request,
        "students/student_form.html",
        {
            "form": form
        }
    )


def student_update(request, id):

    student = get_object_or_404(
        Student,
        id=id
    )

    if request.method == "POST":

        form = StudentForm(
            request.POST,
            instance=student
        )

        if form.is_valid():

            form.save()

            messages.success(
                request,
                "Student updated successfully."
            )

            return redirect(
                "student_list"
            )

    else:

        form = StudentForm(
            instance=student
        )

    return render(
        request,
        "students/student_form.html",
        {
            "form": form
        }
    )


def student_delete(request, id):

    student = get_object_or_404(
        Student,
        id=id
    )

    if request.method == "POST":

        student.delete()

        messages.success(
            request,
            "Student deleted successfully."
        )

        return redirect(
            "student_list"
        )

    return render(
        request,
        "students/student_confirm_delete.html",
        {
            "student": student
        }
    )

29. Complete CRUD Workflow

Student Model
      ↓
Database Migration
      ↓
ModelForm
      ↓
Create View
      ↓
Read/List View
      ↓
Update View
      ↓
Delete View
      ↓
URL Patterns
      ↓
HTML Templates
      ↓
CRUD Application

A complete CRUD application combines models, forms, views, URLs, templates, and database operations into one working system.

30. Django CRUD Project Summary

The Django CRUD project demonstrates the complete lifecycle of database records.

  • Create: Add new student records.
  • Read: Display student records.
  • Update: Edit existing student records.
  • Delete: Remove student records.
  • Use ModelForm to simplify form handling.
  • Use get_object_or_404() for safe record retrieval.
  • Use named URLs for navigation.
  • Use POST requests for data-changing operations.
  • Use CSRF protection in POST forms.
  • CRUD can be combined with search, pagination, and messages.

📌 Key Points

  • CRUD means Create, Read, Update, and Delete.
  • Django Models represent database records.
  • ModelForm simplifies creating and updating records.
  • form.save() creates or updates a record.
  • student.delete() removes a record.
  • get_object_or_404() safely retrieves an object.
  • POST forms should include {% csrf_token %}.
  • CRUD applications can use search, pagination, and messages.

🧠 Quick Quiz

Question: What does the "U" in CRUD stand for?