Skip to content
Open
6 changes: 3 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions task_management/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
# 'rest_framework.permissions.AllowAny',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
Expand Down
2 changes: 1 addition & 1 deletion tasks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
6 changes: 4 additions & 2 deletions tasks/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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):
"""
Expand All @@ -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()
return value.strip()
12 changes: 11 additions & 1 deletion tasks/static/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

.badge-danger {
background-color: red;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: bold;
margin-left: 5px;
}
6 changes: 5 additions & 1 deletion tasks/templates/tasks.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ <h3>{{ task.title }}</h3>
<div class="task-meta">
<span class="task-status status-{{ task.status }}">{{ task.get_status_display }}</span>
<span class="task-date">{{ task.created_at|date:"M d, Y" }}</span>

{% if task.is_overdue %}
<span class="badge-danger">Overdue</span>
{% endif %}
</div>
</div>
<div class="task-card-footer">
Expand Down Expand Up @@ -146,4 +150,4 @@ <h3>Create New Task</h3>
</form>
</div>
</dialog>
{% endblock %}
{% endblock %}
3 changes: 3 additions & 0 deletions tasks/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -449,13 +450,15 @@ 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):
"""
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'

Expand Down