Django CRUD Operations: Step-by-Step Guide

November 19, 2025
25 min read
Lalit Mahato
Django CRUD Operations: Step-by-Step Guide

Django CRUD Operations: Step-by-Step Guide

This tutorial assumes you have already created your project (todo_site) and your app (tasks), and registered the app in settings.py. We will now build the CRUD functionality one operation at a time.

Step 0: The Foundation (Model)

Before we can do any CRUD operations, we need a database table to hold our data.

  1. Define the Model in tasks/models.py:

    from django.db import models
    
    class Task(models.Model):
        title = models.CharField(max_length=200)
        completed = models.BooleanField(default=False)
        created_at = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            return self.title
    
  2. Create the Database Table: Run this in your terminal:

    python manage.py makemigrations
    python manage.py migrate
    

Operation 1: READ (Displaying the List)

The "R" in CRUD. Let's just get a list of tasks showing up on the screen.

  1. Create the View (tasks/views.py): We fetch all tasks from the database and send them to the template.

    from django.shortcuts import render
    from .models import Task
    
    def task_list(request):
        tasks = Task.objects.all()  # Fetch all data
        return render(request, 'tasks/list.html', {'tasks': tasks})
    
  2. Create the URL (todo_list/urls.py): Map the empty path '' to our view.

    from django.urls import path, include
    from . import views
    
    urlpatterns = [
        path('', include('tasks.urls')),
    ]
    
  3. Create the URL (tasks/urls.py): Map the empty path '' to our view.

    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('', views.task_list, name='list'),
    ]
    
  4. Create the Template (templates/tasks/list.html): A simple HTML loop to display data.

    <h1>My To-Do List</h1>
    <ul>
        {% for task in tasks %}
            <li>{{ task.title }}</li>
        {% empty %}
            <li>No tasks yet!</li>
        {% endfor %}
    </ul>
    

Checkpoint: Run python manage.py runserver and go to http://127.0.0.1:8000/. You should see "My To-Do List" and "No tasks yet!".

Operation 2: CREATE (Adding Data)

The "C" in CRUD. Now we need a form to add new tasks.

  1. Define the Form (tasks/forms.py): Create this file to let Django handle the HTML form generation.

    from django import forms
    from .models import Task
    
    class TaskForm(forms.ModelForm):
        class Meta:
            model = Task
            fields = ['title', 'completed']
    
  2. Update the View (tasks/views.py): Modify task_list to handle data submission (POST requests).

    from django.shortcuts import render, redirect # Import redirect
    from .models import Task
    from .forms import TaskForm # Import the Form
    
    def task_list(request):
        tasks = Task.objects.all()
        form = TaskForm() # Empty form for GET request
    
        if request.method == 'POST':
            form = TaskForm(request.POST) # Fill form with data
            if form.is_valid():
                form.save()  # Save to database
                return redirect('list') # Refresh page
    
        return render(request, 'tasks/list.html', {'tasks': tasks, 'form': form})
    
  3. Update the Template (templates/tasks/list.html): Add the form code above the list.

    <h1>My To-Do List</h1>
    
    <!-- New Form Section -->
    <form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Add Task</button>
    </form>
    
    <hr>
    
    <ul>
        {% for task in tasks %}
            <li>{{ task.title }}</li>
        {% endfor %}
    </ul>
    

Checkpoint: Refresh your browser. You can now type a task title, click "Add Task", and see it appear in the list immediately.

Operation 3: UPDATE (Editing Data)

The "U" in CRUD. We need a dedicated page to edit a specific task.

  1. Create the View (tasks/views.py): We need a new view that finds a specific task by its ID (pk) and fills the form with existing data.

    # Add 'get_object_or_404' to imports
    from django.shortcuts import render, redirect, get_object_or_404
    
    # ... existing task_list view ...
    
    def task_update(request, pk):
        task = get_object_or_404(Task, id=pk) # Find task by ID
        form = TaskForm(instance=task) # Fill form with existing data
    
        if request.method == 'POST':
            form = TaskForm(request.POST, instance=task)
            if form.is_valid():
                form.save()
                return redirect('list')
    
        return render(request, 'tasks/update.html', {'form': form})
    
  2. Create the URL (tasks/urls.py): We need a URL that accepts an ID number (like update/1/).

    urlpatterns = [
        path('', views.task_list, name='list'),
        # New URL pattern
        path('update/<int:pk>/', views.task_update, name='update'),
    ]
    
  3. Create the Template (templates/tasks/update.html): A separate page just for editing.

    <h2>Update Task</h2>
    <form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Update</button>
    </form>
    
  4. Link it in the List (templates/tasks/list.html): Add an "Edit" link next to each item.

    <li>
        {{ task.title }}
        <a href="{% url 'update' task.id %}">Edit</a> <!-- New Link -->
    </li>
    

Checkpoint: Refresh the home page. Click "Edit" next to a task. You will go to a new page, change the title or checkbox, click Update, and return to the home page with the changes saved.

Operation 4: DELETE (Removing Data)

The "D" in CRUD. Ideally, we ask for confirmation before deleting.

  1. Create the View (tasks/views.py): Find the task, wait for a POST (confirmation) request, then delete.

    # ... existing views ...
    
    def task_delete(request, pk):
        task = get_object_or_404(Task, id=pk)
    
        if request.method == 'POST':
            task.delete() # Delete from database
            return redirect('list')
    
        return render(request, 'tasks/delete_confirm.html', {'task': task})
    
  2. Create the URL (tasks/urls.py):

    urlpatterns = [
        path('', views.task_list, name='list'),
        path('update/<int:pk>/', views.task_update, name='update'),
        # New URL pattern
        path('delete/<int:pk>/', views.task_delete, name='delete'),
    ]
    
  3. Create the Template (templates/tasks/delete_confirm.html): A warning page.

    <h2>Are you sure?</h2>
    <p>Do you want to delete "{{ task.title }}"?</p>
    
    <form method="POST">
        {% csrf_token %}
        <button type="submit">Yes, Delete</button>
        <a href="{% url 'list' %}">Cancel</a>
    </form>
    
  4. Link it in the List (templates/tasks/list.html): Add a "Delete" link next to the Edit link.

    <li>
        {{ task.title }}
        <a href="{% url 'update' task.id %}">Edit</a>
        <a href="{% url 'delete' task.id %}">Delete</a> <!-- New Link -->
    </li>
    

 

Tags

Django Python
Lalit Mahato

Lalit Mahato

Software Engineer | Machine Learning Enthusiast

Innovative and results-driven software developer with 5+ years of experience in designing, developing, and deploying high-quality software solutions. Proficient in various programming languages and technologies, with a keen interest in …

Comments (0)

No comments yet. Be the first to comment!

Leave a Comment

Search

Categories

Related Posts

Getting Started With Django
Getting Started With Django

Nov 20, 2025

Read More