Django CRUD App Easy Tutorial

Django CRUD App Easy Tutorial

Avatar photoPosted by

Creating a CRUD (Create, Read, Update, Delete) application in Django is a fundamental step in learning web development with this powerful framework. This tutorial will guide you through the process of setting up a Django project connected to a MySQL database and building a basic CRUD application. We’ll use Django’s built-in admin interface to manage our data.

Prerequisites

  • Basic understanding of Python and web development concepts.
  • Python installed on your system (preferably version 3.6+).
  • MySQL server installed and running.
  • MySQL client libraries installed (mysqlclient for Python).

Step 1: Setting Up the Environment

1.1. Install Django and MySQL Client

First, ensure you have pip installed, then install Django and MySQL client:

pip install django mysqlclient

1.2. Create a Django Project

Create a new Django project named djangocrudapp:

django-admin startproject djangocrudapp
cd djangocrudapp

1.3. Create a Django App

Create a new app within your project. We’ll call it projects:

python manage.py startapp projects

1.4 Add Djangpo App to INSTALLED_APPS

add the app projects to the INSTALLED_APPS in djangocrudapp\settings.py:

djangocrudapp\settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'projects'
]

1.5. Configure MySQL Database

Open djangocrudapp\settings.py and update the DATABASES setting to use MySQL:

djangocrudapp\settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_crud_app_db',  # Your database name
        'USER': 'root',  # Your MySQL username
        'PASSWORD': 'password',  # Your MySQL password
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

Step 2: Define Models

2.1. Create a Model

Edit projects\models.py to define a simple model. For this example, we’ll create a Project model:

projects\models.py

from django.db import models
from django.urls import reverse

class Project(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('book_edit', kwargs={'pk': self.pk})

2.2. Register the Model

Register the Project model in the admin interface. Edit projects\admin.py:

projects\admin.py

from django.contrib import admin
from projects.models import Project

admin.site.register(Project)

2.3. Apply Migrations

Generate and apply the migrations to create the necessary database tables:

python manage.py makemigrations
python manage.py migrate

Step 3: Create Views and Templates

3.1. Set Up URLs

Edit djangocrudapp\urls.py to include the URLs for projects:

djangocrudapp\urls.py

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('projects/', include('projects.urls')),
]

Create a urls.py file in the projects directory:

projects\urls.py

from django.urls import path
 
from projects import views
 
urlpatterns = [
    path('', views.project_index, name='project_index'),
    path('show/<int:pk>', views.project_show, name='project_show'),
    path('new', views.project_create, name='project_new'),
    path('store', views.project_store, name='project_store'),
    path('edit/<int:pk>', views.project_edit, name='project_edit'),
    path('update/<int:pk>', views.project_update, name='project_update'),
    path('delete/<int:pk>', views.project_delete, name='project_delete'),
]

3.2. Create Views

Edit projects\views.py to add the necessary views for the CRUD operations:

projects\views.py

from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_http_methods
from django.contrib import messages
from django.forms import ModelForm
from projects.models import Project
 
class ProjectForm(ModelForm):
    class Meta:
        model = Project
        fields = ['name', 'description']

@require_http_methods(["GET"])
def project_index(request, template_name='projects/project_index.html'):
    projects = Project.objects.all()
    data = {}
    data['projects'] = projects
    return render(request, template_name, data)

@require_http_methods(["GET"])
def project_create(request, template_name='projects/project_create.html'):
    data = {}
    return render(request, template_name, data)

@require_http_methods(["POST"])
def project_store(request):
    form = ProjectForm(request.POST or None)
    if form.is_valid():
        form.save()
        messages.success(request, 'Project saved successfully!')

    return redirect('project_index')

@require_http_methods(["GET"])
def project_show(request, pk, template_name='projects/project_show.html'):
    project= get_object_or_404(Project, pk=pk)
    return render(request, template_name, {'project':project})

@require_http_methods(["GET"])
def project_edit(request, pk, template_name='projects/project_edit.html'):
    project= get_object_or_404(Project, pk=pk)
    form = ProjectForm(request.POST or None, instance=project)
    return render(request, template_name, {'form':form, 'project':project})

@require_http_methods(["POST"])
def project_update(request, pk):
    project= get_object_or_404(Project, pk=pk)
    form = ProjectForm(request.POST or None, instance=project)
    method = request.POST.get('_method', '')
    if form.is_valid():
        if method=='PUT':
            form.save()
            messages.success(request, 'Project updated successfully!')
    return redirect('project_index')

@require_http_methods(["POST"])
def project_delete(request, pk):
    project= get_object_or_404(Project, pk=pk)    
    method = request.POST.get('_method', '')
    if method=='DELETE':
        project.delete()
        messages.success(request, 'Project deleted successfully!')
    return redirect('project_index')

3.4. Create Templates

Create a templates/projects directory in projects and add the following HTML files:

projects\templates\projects\base.html

{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <title>Django Project Manager</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
        <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>
    </head>
    <body>
        <div class="container">
            {% block content %}
            {% endblock %}
        </div>
    </body>
</html>

projects\templates\projects\project_index.html

{% extends 'projects/base.html' %}
{% block content %}
<div class="container">
    <h2 class="text-center mt-5 mb-3">Django Project Manager</h2>
    <div class="card">
        <div class="card-header">
            <a class="btn btn-outline-primary" href="{% url "project_new" %}"> 
                Create New Project
            </a>
        </div>
        <div class="card-body">
            {% if messages %}
                {% for message in messages %}
                    {% if message.tags == 'success' %}
                        <div class="alert alert-success">
                            <b>{{ message }}</b>
                        </div>
                    {% endif %}
                {% endfor %}
            {% endif %}
            <table class="table table-bordered">
                <tr>
                    <th>Name</th>
                    <th>Description</th>
                    <th width="240px">Action</th>
                </tr>
                {% for project in projects %}
                <tr>
                    <td>{{ project.name }}</td>
                    <td>{{ project.description }}</td>
                    <td>
                        <a
                            class="btn btn-outline-info"
                            href="{% url "project_show" project.id %}">
                            Show
                        </a>
                        <a
                            class="btn btn-outline-success"
                            href="{% url "project_edit" project.id %}">
                            Edit
                        </a>
                        <form method="post" action="{% url "project_delete" project.id %}">{% csrf_token %}
                            <input type="hidden" name="_method" value="DELETE">
                            <button type="submit" class="btn btn-outline-danger">Delete</button>
                        </form>
                    </td>
                </tr>
                {% endfor %}
            </table>
        </div>
    </div>
</div>
{% endblock %}

projects\templates\projects\project_show.html

{% extends 'projects/base.html' %}
{% block content %}
    <div class="container">
        <h2 class="text-center mt-5 mb-3">Show Project</h2>
        <div class="card">
            <div class="card-header">
                <a class="btn btn-outline-info float-right" href="{% url "project_index" %}"> 
                    View All Projects
                </a>
            </div>
            <div class="card-body">
               <b class="text-muted">Name:</b>
               <p>{{project.name}}</p>
               <b class="text-muted">Description:</b>
               <p>{{project.description}}</p>
            </div>
        </div>
    </div>
{% endblock %}

projects\templates\projects\project_create.html

{% extends 'projects/base.html' %}
{% block content %}
<div class="container">
    <h2 class="text-center mt-5 mb-3">Create New Project</h2>
    <div class="card">
        <div class="card-header">
            <a class="btn btn-outline-info float-right" href="{% url "project_index" %}"> 
                View All Projects
            </a>
        </div>
        <div class="card-body">
            {% if messages %}
                <div class="alert alert-danger">
                    <ul>
                    {% for message in messages %}
                        {% if message.tags == 'error' %}
                            <div class="alert alert-danger">
                                <b>{{ message }}</b>
                            </div>
                        {% endif %}
                    {% endfor %}
                    </ul>
                </div>
            {% endif %}
            <form method="POST" action="{% url "project_store" %}">
                {% csrf_token %}
                <div class="form-group">
                    <label for="name">Name</label>
                    <input type="text" class="form-control" id="name" name="name">
                </div>
                <div class="form-group">
                    <label for="description">Description</label>
                    <textarea class="form-control" id="description" rows="3" name="description"></textarea>
                </div>
               
                <button type="submit" class="btn btn-outline-primary mt-3">Save Project</button>
            </form>
            
        </div>
    </div>
</div>
{% endblock %}

projects\templates\projects\project_edit.html

{% extends 'projects/base.html' %}
{% block content %}
<div class="container">
    <h2 class="text-center mt-5 mb-3">Edit Project</h2>
    <div class="card">
        <div class="card-header">
            <a class="btn btn-outline-info float-right" href="{% url "project_index" %}"> 
                View All Projects
            </a>
        </div>
        <div class="card-body">
            <form method="POST" action="{% url "project_update" project.id %}">
                {% csrf_token %}
                <input type="hidden" name="_method" value="PUT">
                <div class="form-group">
                    <label for="name">Name</label>
                    <input 
                        type="text" 
                        class="form-control" 
                        id="name" 
                        name="name"
                        value="{{project.name}}"
                    >
                </div>
                <div class="form-group">
                    <label for="description">Description</label>
                    <textarea class="form-control" id="description" rows="3" name="description">{{project.description}}</textarea>
                </div>
               
                <button type="submit" class="btn btn-outline-primary mt-3">Save Project</button>
            </form>
            
        </div>
    </div>
</div>
{% endblock %}

Step 4: Run the Application

Start the development server:

python manage.py runserver

and access it http://127.0.0.1:8000/projects/

Admin Dashboard:

To test the admin interface we need to create a user first:

python manage.py createsuperuser 

and access it http://127.0.0.1:8000/admin