Task management systems are essential tools for individuals and organizations to organize, track, and prioritize tasks efficiently. In this article, we'll explore how to build a task management system using django in Python.
Task Management System using Django
Below, are the implementations of the Task Management System using Django in Python.
Starting the Project Folder
To start the project use this command
django-admin startproject task_management_system
cd task_management_system
To start the app use this command
python manage.py startapp task_management_system_app
Now add this app to the ‘settings.py’
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"task_management_system_app",
]
File Structure

Creating a task management system is a great way to improve your Django skills. To take your knowledge even further and master Django, the Django Web Development Course will guide you through advanced concepts.
Setting Necessary Files
task_management_system_app\models.py: Below, code defines Django models for tasks and categories. Tasks are linked to categories and assigned to users, with additional attributes like dates, priority, description, and location for efficient organization and management.
Python
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
class Task(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
assigned_to = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tasks')
start_date = models.DateTimeField()
end_date = models.DateTimeField()
priority = models.IntegerField(default=1)
description = models.TextField(default='')
location = models.CharField(max_length=255, default='')
organizer = models.CharField(max_length=100, default='')
task_management_system_app\views.py: Below Django code includes user authentication, views for task and category management, form handling for user registration and login, as well as authorization checks for admin-only functionalities. It employs decorators like login_required and user_passes_test for access control, ensuring users have appropriate permissions for actions such as task creation, deletion, and updates.
Python
from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from django.contrib import messages
from .models import Category, Task
from django.shortcuts import render, redirect
from .models import Category
from .models import Task
from django.urls import reverse
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required
def is_admin(user):
return user.is_superuser
admin_required = user_passes_test(lambda user: user.is_superuser)
def user_login(request):
if request.method == 'POST':
form = LoginForm(request, request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
if user.is_superuser: # If the user is an admin
return redirect('category_list')
else: # If the user is a normal user
return redirect('user_tasks_list')
else:
form = LoginForm()
return render(request, 'task_management_system_app/login.html', {'form': form})
@login_required
def user_tasks_list(request):
tasks = request.user.tasks.all()
return render(request, 'task_management_system_app/user_tasks_list.html', {'tasks': tasks})
class RegistrationForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'password1', 'password2']
class LoginForm(AuthenticationForm):
class Meta:
model = User
fields = ['username', 'password']
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save()
# login(request, user)
return redirect('login')
else:
form = RegistrationForm()
return render(request, 'task_management_system_app/register.html', {'form': form})
def LogoutPage(request):
logout(request)
return redirect("login")
@login_required
@admin_required
def delete_task(request, task_id):
if request.method == 'POST':
task = Task.objects.get(id=task_id)
task.delete()
return redirect(reverse('category_list'))
@login_required
@admin_required
def create_task(request):
if request.method == 'POST':
# Retrieve data from the POST request
name = request.POST.get('name')
category_id = request.POST.get('category')
start_date = request.POST.get('start_date')
end_date = request.POST.get('end_date')
priority = request.POST.get('priority')
description = request.POST.get('description')
location = request.POST.get('location')
organizer = request.POST.get('organizer')
assigned_to_id = request.POST.get('assigned_to')
category = Category.objects.get(pk=category_id)
task = Task.objects.create(
name=name,
category=category,
start_date=start_date,
end_date=end_date,
priority=priority,
description=description,
location=location,
organizer=organizer,
assigned_to_id=int(assigned_to_id)
)
# Redirect to the task list page
return redirect('category_list')
else:
categories = Category.objects.all()
users = User.objects.all()
return render(request, 'task_management_system_app/create_task.html', {'categories': categories, 'users': users})
@login_required
@admin_required
def update_task(request, task_id):
task = Task.objects.get(pk=task_id)
if request.method == 'POST':
# Update task fields based on form data
task.name = request.POST.get('name')
task.start_date = request.POST.get('start_date')
task.end_date = request.POST.get('end_date')
task.priority = request.POST.get('priority')
task.description = request.POST.get('description')
task.location = request.POST.get('location')
task.organizer = request.POST.get('organizer')
task.assigned_to_id = request.POST.get('assigned_to')
task.save()
return redirect('category_list')
else:
# Render update task page with task data
return render(request, 'task_management_system_app/update_task.html', {'task': task})
@login_required
@admin_required
def category_list(request):
categories = Category.objects.all()
return render(request, 'task_management_system_app/category_list.html', {'categories': categories})
@login_required
@admin_required
def create_category(request):
if request.method == 'POST':
name = request.POST.get('name')
Category.objects.create(name=name)
return redirect('category_list')
return render(request, 'task_management_system_app/create_category.html')
@login_required
@admin_required
def delete_category(request, category_id):
category = Category.objects.get(pk=category_id)
if category.task_set.exists():
messages.error(
request, "You cannot delete this category as it contains tasks.")
else:
category.delete()
messages.success(request, "Category deleted successfully.")
return redirect('category_list')
@login_required
@admin_required
def category_tasks(request, category_id):
category = get_object_or_404(Category, pk=category_id)
tasks = category.task_set.all()
return render(request, 'task_management_system_app/category_tasks.html', {'category': category, 'tasks': tasks})
@login_required
@admin_required
def task_chart(request):
categories = Category.objects.all()
pending_counts = {}
for category in categories:
pending_counts[category.name] = Task.objects.filter(
category=category,
start_date__gt=timezone.now()
).count()
return render(request, 'task_management_system_app/task_chart.html', {'pending_counts': pending_counts})
Creating GUI:
templates/task_management_system_app/category_list.html : The HTML code renders a page to display a list of categories. It includes buttons to create categories, view task charts, and logout. Categories are listed in a table with an option to delete each category. JavaScript is used to display any messages.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Category List</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<!-- Message display section -->
<div class="container mt-5">
<div class="text-center">
<h2>Categories</h2>
</div>
<br>
<a href="{% url 'create_category' %}" class="btn btn-primary mb-3">Create Category</a> <!-- Button to create category -->
<a href="{% url 'task_chart' %}" class="btn btn-info mb-3">View task Chart</a> <!-- Button to view task chart -->
<a href="{% url 'logout' %}" class="btn btn-danger mb-3">Logout</a> <!-- Button to view task chart -->
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Actions</th> <!-- Column for actions -->
</tr>
</thead>
<tbody>
{% for category in categories %}
<tr>
<td>
<a href="{% url 'category_tasks' category.id %}">{{ category.name }}</a>
</td> <!-- Link to category_tasks page -->
<td>
<form method="post" action="{% url 'delete_category' category.id %}" style="display: inline;">
{% csrf_token %}
<button type="submit" class="btn btn-danger btn-sm">Delete</button> <!-- Button to delete category -->
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
// JavaScript function to display the message in a popup form
{% if messages %}
{% for message in messages %}
alert("{{ message }}");
{% endfor %}
{% endif %}
</script>
<!-- Bootstrap JS (Optional - for certain Bootstrap features like modals) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
templates/task_management_system_app/category_tasks.html: Below HTML template showcases tasks within a category, offering options to add new tasks and navigate back. Tasks are listed in a table with details like name, user assignment, start date, time left, priority, and actions. Modals provide additional task information. JavaScript enables priority-based sorting and real-time countdown updates.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ category.name }} tasks</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container mt-5">
<h2 class="text-center">{{ category.name }} tasks</h2>
<br />
<div class="mb-3">
<a href="{% url 'create_task' %}" class="btn btn-primary">Add New task</a> <!-- Button to add new task -->
<a href="{% url 'category_list' %}" class="btn btn-secondary ml-2">Back to Categories</a> <!-- Button to go back to categories -->
</div>
<table id="taskTable" class="table">
<thead>
<tr>
<th>Task name</th>
<th>Assigned to</th>
<th>Start Date</th>
<th>Time Left</th>
<th>
Priority <button class="btn btn-link" onclick="sortByPriority()">▲</button>
</th> <!-- Button for sorting by priority -->
<th>Actions</th> <!-- Column for actions -->
</tr>
</thead>
<tbody>
{% for task in tasks %}
<tr>
<td>{{ task.name }}</td>
<td>{{ task.assigned_to.username }}</td>
<td>{{ task.start_date }}</td>
<td>
<div id="countdown_{{ task.id }}" class="countdown-timer"></div>
</td>
<td>{{ task.priority }}</td>
<td>
<a href="{% url 'update_task' task.id %}" class="btn btn-primary btn-sm">Update</a> <!-- Button to update task -->
<form method="post" action="{% url 'delete_task' task.id %}" style="display: inline;">
{% csrf_token %}
<button type="submit" class="btn btn-danger btn-sm">Delete</button> <!-- Button to delete task -->
</form>
<button type="button" class="btn btn-info btn-sm" data-toggle="modal" data-target="#taskModal_{{ task.id }}">Details</button> <!-- Button to open modal -->
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Modal for task details -->
{% for task in tasks %}
<div class="modal fade" id="taskModal_{{ task.id }}" tabindex="-1" role="dialog" aria-labelledby="taskModalLabel_{{ task.id }}" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="taskModalLabel_{{ task.id }}">{{ task.name }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<p>
<strong>Name:</strong> {{ task.name }}
</p>
<p>
<strong>Category:</strong> {{ task.category.name }}
</p>
<p>
<strong>Assigned to:</strong> {{ task.assigned_to.username }}
</p>
<p>
<strong>Start Date:</strong> {{ task.start_date }}
</p>
<p>
<strong>End Date:</strong> {{ task.end_date }}
</p>
<p>
<strong>Priority:</strong> {{ task.priority }}
</p>
<p>
<strong>Description:</strong> {{ task.description }}
</p>
<p>
<strong>Location:</strong> {{ task.location }}
</p>
<p>
<strong>Organizer:</strong> {{ task.organizer }}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endfor %}
<!-- JavaScript to update countdown timers and sorting -->
<script>
function sortByPriority() {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("taskTable");
switching = true;
while (switching) {
switching = false;
rows = table.getElementsByTagName("tr");
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[3]; // Index of Priority column
y = rows[i + 1].getElementsByTagName("td")[3];
if (parseInt(x.innerHTML) < parseInt(y.innerHTML)) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}
// Function to update countdown timer for each task
function updateCountdownTimers() {
{% for task in tasks %}
// Get the start date of the task and convert it to a JavaScript Date object
var startDate = new Date('{{ task.start_date|date:"Y/m/d H:i:s" }}');
var now = new Date();
// Calculate the time difference between now and the start date
var timeDiff = startDate - now;
// If the task has not started yet, display the countdown timer
if (timeDiff > 0) {
var days = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
var hours = Math.floor((timeDiff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((timeDiff % (1000 * 60)) / 1000);
// Display the countdown timer in the format: DD:HH:MM:SS
document.getElementById('countdown_{{ task.id }}').innerText = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
} else {
// If the task has already started, display a message indicating that it has started
document.getElementById('countdown_{{ task.id }}').innerText = "task has started";
}
{% endfor %}
}
// Call the updateCountdownTimers function every second to update the countdown timers in real-time
setInterval(updateCountdownTimers, 1000);
</script>
<!-- Bootstrap JS (Optional - for certain Bootstrap features like modals) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
templates/task_management_system_app/create_category.html: This HTML template provides a form to create a new category. It includes a field for the category name and a "Create" button to submit the form. Bootstrap CSS is utilized for styling. The design is clean and straightforward, focusing on usability.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Create Category</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container mt-5">
<h2 class="text-center">Create Category</h2>
<br>
<form method="post" action="{% url 'create_category' %}">
{% csrf_token %}
<div class="form-group">
<label for="categoryName">Category Name:</label>
<input type="text" class="form-control" id="categoryName" name="name" placeholder="Enter category name" required />
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
</div>
<!-- Bootstrap JS (Optional - for certain Bootstrap features like dropdowns, modals, etc.) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
templates/task_management_system_app/create_task.html: This HTML template presents a form to add a new task. It includes fields for task name, category selection, user assignment, start and end dates, priority, description, location, and organizer. Bootstrap CSS is used for styling. Additionally, JavaScript is employed to ensure the end date is after the start date.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Add task</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container mt-5">
<h2 class="text-center">Add task</h2>
<br />
<form method="post" action="{% url 'create_task' %}" onsubmit="return validateForm()">
{% csrf_token %}
<div class="form-group">
<label for="taskName">task Name:</label>
<input type="text" class="form-control" id="taskName" name="name" placeholder="Enter task name" required />
</div>
<div class="form-group">
<label for="taskCategory">Category:</label>
<select class="form-control" id="taskCategory" name="category" required>
<option value="">Select category</option>
{% for category in categories %}
<option value="{{ category.id }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="assigned_to">User :</label>
<select class="form-control" id="assigned_to" name="assigned_to" required>
<option value="">Select user</option>
{% for user in users %}
<option value="{{ user.id }}">{{ user.username }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="startDate">Start Date:</label>
<input type="datetime-local" class="form-control" id="startDate" name="start_date" required />
</div>
<div class="form-group">
<label for="endDate">End Date:</label>
<input type="datetime-local" class="form-control" id="endDate" name="end_date" required />
</div>
<div class="form-group">
<label for="priority">Priority:</label>
<input type="number" class="form-control" id="priority" name="priority" min="1" value="1" required />
</div>
<div class="form-group">
<label for="description">Description:</label>
<textarea class="form-control" id="description" name="description" rows="3"></textarea>
</div>
<div class="form-group">
<label for="location">Location:</label>
<input type="text" class="form-control" id="location" name="location" placeholder="Enter task location" />
</div>
<div class="form-group">
<label for="organizer">Organizer:</label>
<input type="text" class="form-control" id="organizer" name="organizer" placeholder="Enter task organizer" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
<!-- Bootstrap JS (Optional - for certain Bootstrap features like dropdowns, modals, etc.) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
function validateForm() {
var startDate = document.getElementById('startDate').value
var endDate = document.getElementById('endDate').value
if (new Date(startDate) >= new Date(endDate)) {
alert('End date must be after the start date.')
return false
}
return true
}
</script>
</body>
</html>
templates/task_management_system_app/task_chart.html: This HTML template renders a bar chart showing pending tasks categorized by category. It utilizes Chart.js for chart rendering. Bootstrap CSS is included for basic styling. JavaScript code dynamically generates chart data based on pending task counts per category.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>task Pending Chart</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<h1 class="mt-5 text-center">Pending tasks by Category</h1>
<br />
<div class="row">
<div class="col-md-6">
<canvas id="taskChart" width="400" height="400"></canvas>
</div>
</div>
</div>
<!-- Bootstrap JS (optional for components that require JS) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var ctx = document.getElementById('taskChart').getContext('2d');
var data = {
labels: [{% for category, count in pending_counts.items %}'{{ category }}',{% endfor %}],
datasets: [{
label: 'Pending tasks',
data: [{% for category, count in pending_counts.items %}{{ count }},{% endfor %}],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
};
var options = {
scales: {
y: {
beginAtZero: true
}
}
};
var myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
</script>
</body>
</html>
templates/task_management_system_app/update_task.html: This HTML template presents a form to update task details, including name, dates, priority, description, location, and organizer. Bootstrap CSS is used for styling. JavaScript ensures end date validation against the start date. The design focuses on user-friendly task modification.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Update task</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container mt-5">
<h2 class="text-center">Update task</h2>
<br>
<form method="post" id="updatetaskForm">
{% csrf_token %}
<div class="form-group">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" name="name" value="{{ task.name }}" required />
</div>
<div class="form-group">
<label for="start_date">Start Date:</label>
<input type="datetime-local" class="form-control" id="start_date" name="start_date" value="{{ task.start_date }}" required />
</div>
<div class="form-group">
<label for="end_date">End Date:</label>
<input type="datetime-local" class="form-control" id="end_date" name="end_date" value="{{ task.end_date }}" required />
<small id="end_date_error" class="form-text text-danger"></small>
</div>
<div class="form-group">
<label for="priority">Priority:</label>
<input type="number" class="form-control" id="priority" name="priority" value="{{ task.priority }}" required />
</div>
<div class="form-group">
<label for="description">Description:</label>
<textarea class="form-control" id="description" name="description" required>{{ task.description }}</textarea>
</div>
<div class="form-group">
<label for="location">Location:</label>
<input type="text" class="form-control" id="location" name="location" value="{{ task.location }}" required />
</div>
<div class="form-group">
<label for="organizer">Organizer:</label>
<input type="text" class="form-control" id="organizer" name="organizer" value="{{ task.organizer }}" required />
</div>
<button type="submit" class="btn btn-primary">Save task</button>
</form>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
// Function to validate end date is after start date
function validateEndDate() {
var startDate = new Date(document.getElementById('start_date').value)
var endDate = new Date(document.getElementById('end_date').value)
if (endDate <= startDate) {
document.getElementById('end_date_error').innerText = 'End date must be after start date'
return false
} else {
document.getElementById('end_date_error').innerText = ''
return true
}
}
// Add task listener to form submission for validation
document.getElementById('updatetaskForm').addtaskListener('submit', function (task) {
if (!validateEndDate()) {
task.prtaskDefault() // Prtask form submission if validation fails
}
})
</script>
</body>
</html>
templates/task_management_system_app/user_task_list.html: This HTML template displays tasks belonging to a specific category. It includes task details such as name, start date, time left (countdown timer), priority, and actions. Bootstrap CSS is utilized for styling, and JavaScript is used to update countdown timers and enable sorting by priority.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ category.name }} tasks</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container mt-5">
<h2 class="text-center">{{ category.name }} tasks</h2>
<br />
<div class="mb-3">
<a href="{% url 'logout' %}" class="btn btn-danger ml-2">logout</a> <!-- Button to go back to categories -->
</div>
<table id="taskTable" class="table">
<thead>
<tr>
<th>Task name</th>
<th>Start Date</th>
<th>Time Left</th>
<th>
Priority <button class="btn btn-link" onclick="sortByPriority()">▲</button>
</th> <!-- Button for sorting by priority -->
<th>Actions</th> <!-- Column for actions -->
</tr>
</thead>
<tbody>
{% for task in tasks %}
<tr>
<td>{{ task.name }}</td>
<td>{{ task.start_date }}</td>
<td>
<div id="countdown_{{ task.id }}" class="countdown-timer"></div>
</td>
<td>{{ task.priority }}</td>
<td>
<button type="button" class="btn btn-info btn-sm" data-toggle="modal" data-target="#taskModal_{{ task.id }}">Details</button> <!-- Button to open modal -->
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Modal for task details -->
{% for task in tasks %}
<div class="modal fade" id="taskModal_{{ task.id }}" tabindex="-1" role="dialog" aria-labelledby="taskModalLabel_{{ task.id }}" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="taskModalLabel_{{ task.id }}">{{ task.name }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<p>
<strong>Name:</strong> {{ task.name }}
</p>
<p>
<strong>Category:</strong> {{ task.category.name }}
</p>
<p>
<strong>Assigned to:</strong> {{ task.assigned_to.username }}
</p>
<p>
<strong>Start Date:</strong> {{ task.start_date }}
</p>
<p>
<strong>End Date:</strong> {{ task.end_date }}
</p>
<p>
<strong>Priority:</strong> {{ task.priority }}
</p>
<p>
<strong>Description:</strong> {{ task.description }}
</p>
<p>
<strong>Location:</strong> {{ task.location }}
</p>
<p>
<strong>Organizer:</strong> {{ task.organizer }}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endfor %}
<!-- JavaScript to update countdown timers and sorting -->
<script>
function sortByPriority() {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById("taskTable");
switching = true;
while (switching) {
switching = false;
rows = table.getElementsByTagName("tr");
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[3]; // Index of Priority column
y = rows[i + 1].getElementsByTagName("td")[3];
if (parseInt(x.innerHTML) < parseInt(y.innerHTML)) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}
// Function to update countdown timer for each task
function updateCountdownTimers() {
{% for task in tasks %}
// Get the start date of the task and convert it to a JavaScript Date object
var startDate = new Date('{{ task.start_date|date:"Y/m/d H:i:s" }}');
var now = new Date();
// Calculate the time difference between now and the start date
var timeDiff = startDate - now;
// If the task has not started yet, display the countdown timer
if (timeDiff > 0) {
var days = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
var hours = Math.floor((timeDiff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((timeDiff % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((timeDiff % (1000 * 60)) / 1000);
// Display the countdown timer in the format: DD:HH:MM:SS
document.getElementById('countdown_{{ task.id }}').innerText = days + "d " + hours + "h "
+ minutes + "m " + seconds + "s ";
} else {
// If the task has already started, display a message indicating that it has started
document.getElementById('countdown_{{ task.id }}').innerText = "task has started";
}
{% endfor %}
}
// Call the updateCountdownTimers function every second to update the countdown timers in real-time
setInterval(updateCountdownTimers, 1000);
</script>
<!-- Bootstrap JS (Optional - for certain Bootstrap features like modals) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>
templates/task_management_system_app/login.html: This HTML template represents a login page. It includes a form for users to input their credentials (e.g., username and password) and a "Login" button to submit the form. Additionally, there is a link to the registration page for users who do not have an account yet.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h2 class="mt-4 mb-4">Login</h2>
<form method="post" class="mb-4">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Login</button>
</form>
<p>
Don't have an account? <a href="{% url 'register' %}" class="btn btn-link">Register here</a>.
</p>
</div>
</div>
</div>
</body>
</html>
templates/task_management_system_app/register.html: This HTML template represents a registration page. It includes a form for users to input their registration details (e.g., username, email, and password) and a "Register" button to submit the form.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Register</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<h2 class="mt-4 mb-4">Register</h2>
<form method="post" class="mb-4">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Register</button>
</form>
<p>Already have an account? <a href="{% url 'login' %}" class="btn btn-link">Login here</a>.</p>
</div>
</div>
</div>
</body>
</html>
task_management_system/urls.py : In below code the urlpatterns variable in a Django project maps URLs to view functions or classes. It handles routes for admin access, user tasks, authentication, category operations, task operations, and generating task charts, facilitating navigation and interaction within the web application.
Python
from django.contrib import admin
from django.urls import path
from task_management_system_app import views
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth.views import LogoutView
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', views.user_tasks_list, name='user_tasks_list'),
path('accounts/', include('django.contrib.auth.urls')),
path('register/', views.register, name='register'),
path('login/', views.user_login, name='login'),
path("logout/", views.LogoutPage, name="logout"),
path('', views.category_list, name='category_list'),
path('categories/create/', views.create_category, name='create_category'),
path('categories/<int:category_id>/', views.category_tasks, name='category_tasks'),
path('categories/delete/<int:category_id>/', views.delete_category, name='delete_category'),
path('tasks/create/', views.create_task, name='create_task'),
path('tasks/update/<int:task_id>/', views.update_task, name='update_task'),
path('tasks/delete/<int:task_id>/', views.delete_task, name='delete_task'),
path('task-chart/', views.task_chart, name='task_chart'),
]
task_management_system/admin.py : This Django admin setup allows easy management of Category and Task models. It offers straightforward access to categories with search capabilities by name. For tasks, it provides detailed information such as start and end dates, priority, and filters for efficient organization.
Python
from django.contrib import admin
from .models import Category, Task
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ('name',)
search_fields = ('name',)
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ('name', 'category', 'start_date', 'end_date', 'priority')
list_filter = ('category', 'priority')
search_fields = ('name', 'category__name', 'description', 'location', 'organizer')
Deployment of the Project
Run these commands to apply the migrations:
python3 manage.py makemigrations
python3 manage.py migrate
Create superuser using the below command
python3 manage.py createsuperuser
Run the server with the help of following command:
python3 manage.py runserver
Output






Video Demonstration
.gif)
Similar Reads
Python Tutorial | Learn Python Programming Language Python Tutorial â Python is one of the most popular programming languages. Itâs simple to use, packed with features and supported by a wide range of libraries and frameworks. Its clean syntax makes it beginner-friendly.Python is:A high-level language, used in web development, data science, automatio
10 min read
Python Interview Questions and Answers Python is the most used language in top companies such as Intel, IBM, NASA, Pixar, Netflix, Facebook, JP Morgan Chase, Spotify and many more because of its simplicity and powerful libraries. To crack their Online Assessment and Interview Rounds as a Python developer, we need to master important Pyth
15+ min read
Non-linear Components In electrical circuits, Non-linear Components are electronic devices that need an external power source to operate actively. Non-Linear Components are those that are changed with respect to the voltage and current. Elements that do not follow ohm's law are called Non-linear Components. Non-linear Co
11 min read
Python OOPs Concepts Object Oriented Programming is a fundamental concept in Python, empowering developers to build modular, maintainable, and scalable applications. By understanding the core OOP principles (classes, objects, inheritance, encapsulation, polymorphism, and abstraction), programmers can leverage the full p
11 min read
Python Projects - Beginner to Advanced Python is one of the most popular programming languages due to its simplicity, versatility, and supportive community. Whether youâre a beginner eager to learn the basics or an experienced programmer looking to challenge your skills, there are countless Python projects to help you grow.Hereâs a list
10 min read
Python Exercise with Practice Questions and Solutions Python Exercise for Beginner: Practice makes perfect in everything, and this is especially true when learning Python. If you're a beginner, regularly practicing Python exercises will build your confidence and sharpen your skills. To help you improve, try these Python exercises with solutions to test
9 min read
Python Programs Practice with Python program examples is always a good choice to scale up your logical understanding and programming skills and this article will provide you with the best sets of Python code examples.The below Python section contains a wide collection of Python programming examples. These Python co
11 min read
Spring Boot Tutorial Spring Boot is a Java framework that makes it easier to create and run Java applications. It simplifies the configuration and setup process, allowing developers to focus more on writing code for their applications. This Spring Boot Tutorial is a comprehensive guide that covers both basic and advance
10 min read
Class Diagram | Unified Modeling Language (UML) A UML class diagram is a visual tool that represents the structure of a system by showing its classes, attributes, methods, and the relationships between them. It helps everyone involved in a projectâlike developers and designersâunderstand how the system is organized and how its components interact
12 min read
Enumerate() in Python enumerate() function adds a counter to each item in a list or other iterable. It turns the iterable into something we can loop through, where each item comes with its number (starting from 0 by default). We can also turn it into a list of (number, item) pairs using list().Let's look at a simple exam
3 min read