diff --git a/requirements.txt b/requirements.txt index 4c9c661..b45a49c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,14 @@ asgiref==3.8.1 Brotli==1.1.0 -click==8.2.1 +click==8.1.8 colorama==0.4.6 dj-database-url==3.0.0 -Django==5.2.3 +Django==4.2.23 djangorestframework==3.16.0 gunicorn==23.0.0 h11==0.16.0 packaging==25.0 -psycopg2-binary==2.9.10 +psycopg2-binary==2.9.9 python-decouple==3.8 sqlparse==0.5.3 typing_extensions==4.14.0 diff --git a/task_management/settings.py b/task_management/settings.py index 0530f60..fa412ec 100644 --- a/task_management/settings.py +++ b/task_management/settings.py @@ -136,6 +136,7 @@ REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', + # 'rest_framework.permissions.AllowAny', ], 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.SessionAuthentication', diff --git a/tasks/models.py b/tasks/models.py index e42264c..a869b1a 100644 --- a/tasks/models.py +++ b/tasks/models.py @@ -20,7 +20,7 @@ class Status(models.TextChoices): due_date = models.DateTimeField(null=True, blank=True, verbose_name='Due Date') priority = models.CharField(max_length=10, choices=Priority.choices, default=Priority.LOW) status = models.CharField(max_length=20, choices=Status.choices, default=Status.PENDING) - user = models.ForeignKey(User, on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE, blank= True, null=True) def __str__(self): return f"{self.title} by: {self.user.username}" diff --git a/tasks/serializers.py b/tasks/serializers.py index 0334111..76930a7 100644 --- a/tasks/serializers.py +++ b/tasks/serializers.py @@ -6,7 +6,7 @@ class TaskSerializer(serializers.ModelSerializer): Serializer for Task Model Convierte entre instancias de Task y JSON """ - is_overdue = serializers.ReadOnlyField() + is_overdue = serializers.SerializerMethodField() user = serializers.StringRelatedField(read_only=True) @@ -24,6 +24,8 @@ class Meta: 'is_overdue' ] read_only_fields = ['id', 'created_at', 'updated_at', 'user'] + def get_is_overdue(self, obj): + return obj.due_date and obj.due_date < date.today() class TaskCreateUpdateSerializer(serializers.ModelSerializer): """ @@ -47,4 +49,4 @@ def validate_title(self, value): """Validación personalizada para título""" if not value or not value.strip(): raise serializers.ValidationError("Title cannot be empty") - return value.strip() \ No newline at end of file + return value.strip() diff --git a/tasks/static/styles.css b/tasks/static/styles.css index 07a508d..4b4340f 100644 --- a/tasks/static/styles.css +++ b/tasks/static/styles.css @@ -1211,4 +1211,14 @@ form input:focus, form textarea:focus, form select:focus { border-color: #667eea; background: white; box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); -} \ No newline at end of file +} + +.badge-danger { + background-color: red; + color: white; + padding: 4px 8px; + border-radius: 4px; + font-size: 0.75rem; + font-weight: bold; + margin-left: 5px; +} diff --git a/tasks/templates/tasks.html b/tasks/templates/tasks.html index c40b7f6..32cd703 100644 --- a/tasks/templates/tasks.html +++ b/tasks/templates/tasks.html @@ -63,6 +63,10 @@

{{ task.title }}

{{ task.get_status_display }} {{ task.created_at|date:"M d, Y" }} + + {% if task.is_overdue %} + Overdue + {% endif %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/tasks/views.py b/tasks/views.py index 18e1680..3382587 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -434,6 +434,7 @@ class TaskListAPIView(generics.ListCreateAPIView): API para listar tareas (GET) y crear nuevas tareas (POST) """ permission_classes = [IsAuthenticated] + # permission_classes = [AllowAny] serializer_class = TaskSerializer def get_queryset(self): @@ -449,6 +450,7 @@ def get_serializer_class(self): def perform_create(self, serializer): """Asignar usuario al crear tarea""" serializer.save(user=self.request.user) + # serializer.save(user=None) class TaskDetailAPIView(generics.RetrieveUpdateDestroyAPIView): @@ -456,6 +458,7 @@ class TaskDetailAPIView(generics.RetrieveUpdateDestroyAPIView): API para obtener (GET), actualizar (PUT) o eliminar (DELETE) una tarea específica """ permission_classes = [IsAuthenticated] + # permission_classes = [AllowAny] serializer_class = TaskSerializer lookup_field = 'id'