Contents
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