diff --git a/join/settings.py b/join/settings.py index 19b822e..e34e0bb 100644 --- a/join/settings.py +++ b/join/settings.py @@ -101,6 +101,16 @@ TEMPLATES = [ WSGI_APPLICATION = 'join.wsgi.application' +# Redis +CACHES = { + 'default': { + 'BACKEND': 'django_redis.cache.RedisCache', + 'LOCATION': 'redis://127.0.0.1:6379/1', + 'OPTIONS': { + 'CLIENT_CLASS': 'django_redis.client.DefaultClient', + } + } +} # Database # https://docs.djangoproject.com/en/5.1/ref/settings/#databases diff --git a/task_app/caching.py b/task_app/caching.py new file mode 100644 index 0000000..f90c5df --- /dev/null +++ b/task_app/caching.py @@ -0,0 +1,16 @@ +from django.core.cache import cache +from .models import Task + +def get_cached_tasks_by_status(status): + cache_key = f"tasks_by_status_{status}" + + cached_tasks = cache.get(cache_key) + + if cached_tasks is not None: + return cached_tasks + + tasks = Task.objects.filter(status=status) + + cache.set(cache_key, tasks, timeout=3600) + + return tasks \ No newline at end of file diff --git a/task_app/models.py b/task_app/models.py index 6c9d577..272cb29 100644 --- a/task_app/models.py +++ b/task_app/models.py @@ -1,6 +1,7 @@ import uuid from django.db import models from django.contrib.auth import get_user_model +from django.core.cache import cache User = get_user_model() @@ -13,7 +14,7 @@ class Task(models.Model): description = models.TextField(blank=True, null=True) category = models.CharField(max_length=50, choices=[('Technical Task', 'Technical Task'), ('User Story', 'User Story')]) priority = models.CharField(max_length=50, choices=[('low', 'Low'), ('medium', 'Medium'), ('urgent', 'Urgent')]) - status = models.CharField(max_length=50, choices=[('todo', 'Todo'), ('in_progress', 'In Progress'), ('await_feedback', 'Await feedback'), ('done', 'Done')]) + status = models.CharField(max_length=50, choices=[('todo', 'Todo'), ('inprogress', 'In Progress'), ('awaitfeedback', 'Await feedback'), ('done', 'Done')]) date = models.DateField() creator = models.ForeignKey(User, related_name="created_tasks", on_delete=models.CASCADE) diff --git a/task_app/views.py b/task_app/views.py index 5402687..0c58342 100644 --- a/task_app/views.py +++ b/task_app/views.py @@ -1,21 +1,64 @@ from rest_framework import viewsets +from rest_framework.response import Response +from rest_framework import status from .models import Task, SubTask, AssignedTask from .serializers import TaskSerializer, SubTaskSerializer, AssignedTaskSerializer +from rest_framework.decorators import action +from .caching import get_cached_tasks_by_status +from user_app.caching import get_cached_user class TaskViewSet(viewsets.ModelViewSet): - queryset = Task.objects.all() + queryset = Task.objects.all() serializer_class = TaskSerializer def get_queryset(self): - status = self.request.query_params.get('status', None) - if status: - return Task.objects.filter(status=status) + status_param = self.request.query_params.get('status', None) + + if status_param: + tasks = get_cached_tasks_by_status(status_param) + return tasks return Task.objects.all() + def get(self, request, status=None): + tasks = get_cached_tasks_by_status(status) + task_data = [] + + for task in tasks: + creator = get_cached_user(task['creator_id']) + assignees = [get_cached_user(assignee['user_id']) for assignee in task['assigned_users']] + + task_data.append({ + 'title': task['title'], + 'description': task['description'], + 'status': task['status'], + 'creator': creator.first_name if creator else None, + 'assignees': [assignee.first_name for assignee in assignees if assignee] + }) + + return Response(task_data, status=status.HTTP_200_OK) + + @action(detail=True, methods=['put']) + def update_status(self, request, pk=None): + task = self.get_object() + status = request.data.get('status') + + if not status: + return Response({'status': 'failed', 'message': 'No status provided'}, status=400) + + valid_statuses = ['todo', 'inprogress', 'awaitfeedback', 'done'] + if status not in valid_statuses: + return Response({'status': 'failed', 'message': f'Invalid status: {status}'}, status=400) + + task.status = status + task.save() + return Response({'status': 'updated', 'task_id': task.id}) + + class SubTaskViewSet(viewsets.ModelViewSet): queryset = SubTask.objects.all() serializer_class = SubTaskSerializer + class AssignedTaskViewSet(viewsets.ModelViewSet): queryset = AssignedTask.objects.all() serializer_class = AssignedTaskSerializer \ No newline at end of file diff --git a/user_app/admin.py b/user_app/admin.py index d0ff6a3..6b7a580 100644 --- a/user_app/admin.py +++ b/user_app/admin.py @@ -9,7 +9,7 @@ class UserAdmin(admin.ModelAdmin): fieldsets = ( (None, { - 'fields': ('first_name', 'last_name', 'email', 'phone') + 'fields': ('first_name', 'last_name', 'email', 'phone', 'password') }), ('Additional Info', { 'fields': ('initials', 'color', 'status', 'last_login') diff --git a/user_app/caching.py b/user_app/caching.py new file mode 100644 index 0000000..a453901 --- /dev/null +++ b/user_app/caching.py @@ -0,0 +1,19 @@ +from django.core.cache import cache +from .models import User +from django.core.exceptions import ObjectDoesNotExist + +def get_cached_user(user_id): + cache_key = f"user_{user_id}" + + cached_user = cache.get(cache_key) + if cached_user is not None: + return cached_user + + try: + user = User.objects.get(id=user_id) + except ObjectDoesNotExist: + return None + + cache.set(cache_key, user, timeout=3600) + + return user \ No newline at end of file diff --git a/user_app/models.py b/user_app/models.py index c290c36..e0ff81f 100644 --- a/user_app/models.py +++ b/user_app/models.py @@ -30,7 +30,7 @@ class User(AbstractBaseUser, PermissionsMixin): uId = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) id = models.CharField(primary_key=True, default=generate_uuid_without_dashes, max_length=32,editable=False, unique=True) first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) + last_name = models.CharField(max_length=50, blank=True, null=True) email = models.EmailField(unique=True) phone = models.CharField(max_length=20, blank=True, null=True) initials = models.CharField(max_length=10, blank=True)