Open In App

Create Task Management System using Django

Last Updated : 03 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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

pop

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.

Python3
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.

Python3
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()">&#x25B2;</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">&times;</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/bootstrap@5.3.0-alpha1/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/bootstrap@5.3.0-alpha1/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()">&#x25B2;</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">&times;</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.

Python3
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.

Python3
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

Screenshot-2024-03-26-102017

Screenshot-2024-03-26-102023

Screenshot-2024-03-26-102036

Screenshot-2024-03-26-102055

Screenshot-2024-03-26-102103


Screenshot-2024-03-26-102142

Screenshot-2024-03-26-102148Video Demonstration

Recording-2024-03-26-102326-(online-video-cuttercom)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads