feat: integrate Redis for caching
This commit is contained in:
parent
1d7b836eb6
commit
cd1e6b2a2d
7 changed files with 96 additions and 7 deletions
|
|
@ -101,6 +101,16 @@ TEMPLATES = [
|
||||||
|
|
||||||
WSGI_APPLICATION = 'join.wsgi.application'
|
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
|
# Database
|
||||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||||
|
|
|
||||||
16
task_app/caching.py
Normal file
16
task_app/caching.py
Normal file
|
|
@ -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
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import uuid
|
import uuid
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
@ -13,7 +14,7 @@ class Task(models.Model):
|
||||||
description = models.TextField(blank=True, null=True)
|
description = models.TextField(blank=True, null=True)
|
||||||
category = models.CharField(max_length=50, choices=[('Technical Task', 'Technical Task'), ('User Story', 'User Story')])
|
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')])
|
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()
|
date = models.DateField()
|
||||||
|
|
||||||
creator = models.ForeignKey(User, related_name="created_tasks", on_delete=models.CASCADE)
|
creator = models.ForeignKey(User, related_name="created_tasks", on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,64 @@
|
||||||
from rest_framework import viewsets
|
from rest_framework import viewsets
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import status
|
||||||
from .models import Task, SubTask, AssignedTask
|
from .models import Task, SubTask, AssignedTask
|
||||||
from .serializers import TaskSerializer, SubTaskSerializer, AssignedTaskSerializer
|
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):
|
class TaskViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Task.objects.all()
|
queryset = Task.objects.all()
|
||||||
serializer_class = TaskSerializer
|
serializer_class = TaskSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
status = self.request.query_params.get('status', None)
|
status_param = self.request.query_params.get('status', None)
|
||||||
if status:
|
|
||||||
return Task.objects.filter(status=status)
|
if status_param:
|
||||||
|
tasks = get_cached_tasks_by_status(status_param)
|
||||||
|
return tasks
|
||||||
return Task.objects.all()
|
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):
|
class SubTaskViewSet(viewsets.ModelViewSet):
|
||||||
queryset = SubTask.objects.all()
|
queryset = SubTask.objects.all()
|
||||||
serializer_class = SubTaskSerializer
|
serializer_class = SubTaskSerializer
|
||||||
|
|
||||||
|
|
||||||
class AssignedTaskViewSet(viewsets.ModelViewSet):
|
class AssignedTaskViewSet(viewsets.ModelViewSet):
|
||||||
queryset = AssignedTask.objects.all()
|
queryset = AssignedTask.objects.all()
|
||||||
serializer_class = AssignedTaskSerializer
|
serializer_class = AssignedTaskSerializer
|
||||||
|
|
@ -9,7 +9,7 @@ class UserAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
'fields': ('first_name', 'last_name', 'email', 'phone')
|
'fields': ('first_name', 'last_name', 'email', 'phone', 'password')
|
||||||
}),
|
}),
|
||||||
('Additional Info', {
|
('Additional Info', {
|
||||||
'fields': ('initials', 'color', 'status', 'last_login')
|
'fields': ('initials', 'color', 'status', 'last_login')
|
||||||
|
|
|
||||||
19
user_app/caching.py
Normal file
19
user_app/caching.py
Normal file
|
|
@ -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
|
||||||
|
|
@ -30,7 +30,7 @@ class User(AbstractBaseUser, PermissionsMixin):
|
||||||
uId = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
|
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)
|
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)
|
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)
|
email = models.EmailField(unique=True)
|
||||||
phone = models.CharField(max_length=20, blank=True, null=True)
|
phone = models.CharField(max_length=20, blank=True, null=True)
|
||||||
initials = models.CharField(max_length=10, blank=True)
|
initials = models.CharField(max_length=10, blank=True)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue