As a developer, while working on a project for a client, I had to build a simple employee management system. The client wanted a web application where they could add new employees, view their details, update them, and delete records when needed.
While this sounds like a common requirement, it is the foundation of most applications we build today. These four essential operations are known as CRUD: Create, Read, Update, and Delete.
In this tutorial, I will walk you through how I built a CRUD application using Django and PostgreSQL. I will share the exact steps I followed, the code I wrote, and the lessons I learned along the way.
What is CRUD?
CRUD stands for:
- Create – Adding new records to the database.
- Read – Retrieving and displaying existing records.
- Update – Modifying existing records.
- Delete – Removing records from the database.
Every application you use daily, from online shopping sites to banking apps, relies on CRUD operations.
Django with PostgreSQL
I chose Django because it is a powerful Python framework that makes web development fast and secure. PostgreSQL is my database of choice because it is reliable, open-source, and widely used in enterprise applications in the USA.
When combined, Django and PostgreSQL give us a robust stack for building scalable applications.
Set Up the Project
Before we start coding, make sure you install the following:
- Python 3.x
- PostgreSQL (with pgAdmin if you prefer a GUI)
- Django (latest version)
- psycopg2 (PostgreSQL adapter for Python)
You can install Django and psycopg2 using pip:
pip install django psycopg2Step 1 – Create a Django Project
Open your terminal and run:
django-admin startproject employee_project
cd employee_projectThis will create a new Django project.
Step 2 – Configure PostgreSQL Database
Open the settings.py file inside your project and update the DATABASES section:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'employee_db',
'USER': 'postgres',
'PASSWORD': 'your_password',
'HOST': 'localhost',
'PORT': '5432',
}
}Make sure you create the database in PostgreSQL first:
CREATE DATABASE employee_db;Step 3 – Create a Django App
Inside your project, create a new app:
python manage.py startapp employeesAdd employees to the INSTALLED_APPS list in settings.py.
Step 4 – Create the Model
Inside employees/models.py:
from django.db import models
class Employee(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
department = models.CharField(max_length=100)
salary = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"{self.first_name} {self.last_name}"Run migrations to create the table:
python manage.py makemigrations
python manage.py migrateStep 5 – Create Forms
Inside employees/forms.py:
from django import forms
from .models import Employee
class EmployeeForm(forms.ModelForm):
class Meta:
model = Employee
fields = ['first_name', 'last_name', 'email', 'department', 'salary']Step 6 – Create Views for CRUD
Inside employees/views.py:
from django.shortcuts import render, redirect, get_object_or_404
from .models import Employee
from .forms import EmployeeForm
# Read - List Employees
def employee_list(request):
employees = Employee.objects.all()
return render(request, 'employees/employee_list.html', {'employees': employees})
# Create - Add Employee
def employee_create(request):
if request.method == 'POST':
form = EmployeeForm(request.POST)
if form.is_valid():
form.save()
return redirect('employee_list')
else:
form = EmployeeForm()
return render(request, 'employees/employee_form.html', {'form': form})
# Update - Edit Employee
def employee_update(request, pk):
employee = get_object_or_404(Employee, pk=pk)
if request.method == 'POST':
form = EmployeeForm(request.POST, instance=employee)
if form.is_valid():
form.save()
return redirect('employee_list')
else:
form = EmployeeForm(instance=employee)
return render(request, 'employees/employee_form.html', {'form': form})
# Delete - Remove Employee
def employee_delete(request, pk):
employee = get_object_or_404(Employee, pk=pk)
if request.method == 'POST':
employee.delete()
return redirect('employee_list')
return render(request, 'employees/employee_confirm_delete.html', {'employee': employee})Step 7 – Configure URLs
Inside employees/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.employee_list, name='employee_list'),
path('create/', views.employee_create, name='employee_create'),
path('update/<int:pk>/', views.employee_update, name='employee_update'),
path('delete/<int:pk>/', views.employee_delete, name='employee_delete'),
]In employee_project/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('employees.urls')),
]Step 8 – Create Templates
Inside employees/templates/employees/ create the following HTML files:
employee_list.html
<h2>Employee List</h2>
<a href="{% url 'employee_create' %}">Add Employee</a>
<ul>
{% for employee in employees %}
<li>
{{ employee.first_name }} {{ employee.last_name }} - {{ employee.department }}
<a href="{% url 'employee_update' employee.id %}">Edit</a>
<a href="{% url 'employee_delete' employee.id %}">Delete</a>
</li>
{% endfor %}
</ul>employee_form.html
<h2>Employee Form</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
<a href="{% url 'employee_list' %}">Back</a>employee_confirm_delete.html
<h2>Are you sure you want to delete {{ employee.first_name }} {{ employee.last_name }}?</h2>
<form method="post">
{% csrf_token %}
<button type="submit">Yes, Delete</button>
</form>
<a href="{% url 'employee_list' %}">Cancel</a>Step 9 – Run the Server
Start the server:
python manage.py runserverVisit http://127.0.0.1:8000/ in your browser. You should now see the employee list and be able to create, update, and delete employees.
I executed the above example code and added the screenshot below.

Add employee details here,



Alternative Method – Use Django Rest Framework (DRF)
Sometimes, instead of building HTML templates, I expose CRUD operations as REST APIs. This is especially useful when the frontend is built using React or Angular.
With Django Rest Framework (DRF), you can quickly create serializers and viewsets that handle CRUD automatically.
Example serializer (serializers.py):
from rest_framework import serializers
from .models import Employee
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = '__all__'Example viewset (views.py):
from rest_framework import viewsets
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeViewSet(viewsets.ModelViewSet):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializerThis method is faster if you are building APIs for mobile apps or SPAs.
In this tutorial, I showed you how I built a CRUD application with Django and PostgreSQL. We started by setting up the database, creating models, forms, and views, and then connecting everything with templates.
I also shared an alternative method using Django Rest Framework for building APIs.
Both approaches work great. If you are building a traditional web app, stick with templates. If you are building APIs for modern frontend frameworks, DRF is the right choice.
You may read other Django articles:

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.