You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django考勤系统POST接口返回空{}及400 Bad Request问题排查

考勤接口返回空{} + 400 Bad Request的问题修复

先看直接导致空返回的核心问题:视图post方法里的教师权限判断分支漏写return,且逻辑搞反,导致不管权限是否通过,都直接返回空的serializer.errors(序列化验证通过时,errors为空字典)。除此之外还有序列化器、权限判断的其他问题,下面逐一修复:


问题拆解

1. 视图层逻辑错误(直接引发空400)

在AttendanceListCreateAPIView.post的教师权限判断代码中:

  • 第一个Response未加return,代码会直接走到下一行返回serializer.errors,而此时序列化已通过,errors为空,所以返回空{}
  • 权限逻辑写反:应该是教师的homeroom与学生room不一致时才无权限,而非相等时
  • 教师权限通过后无保存数据的逻辑,直接返回400,完全不符合需求

2. 序列化器的无效配置与错误赋值

  • 序列化器Meta类中的constraints是多余的,UniqueConstraint仅需在模型层定义,序列化器不识别该配置
  • create方法中Date=datetime.today是引用方法对象而非调用方法,应改为datetime.today();且模型中Date已设置auto_now_add=True,会自动填充创建时间,无需手动赋值

3. 权限判断的其他漏洞

  • 班干部判断中的user.perms.is_monitor应改为perms.is_monitor,因为perms已经是获取到的Perm实例,不是user的属性
  • 分支逻辑存在漏洞:教师权限通过后未执行保存操作,直接返回错误

修正后的完整代码

视图层(Attendance/views.py)

from django.core.exceptions import ObjectDoesNotExist
from rest_framework import status
from rest_framework.response import Response
from rest_framework.generics import CreateAPIView
from .models import Attendance
from .serializers import AttendanceSerializer
from .permissions import IsClassPart

class AttendanceListCreateAPIView(CreateAPIView):
    permission_classes = [IsClassPart]
    queryset = Attendance.objects.all()
    serializer_class = AttendanceSerializer

    def post(self, request, format=None):
        user = request.user
        try:
            perms = Perm.objects.get(user=user)
        except ObjectDoesNotExist:
            perms = None
        
        # 必须传入request到context,否则序列化器无法获取当前用户
        serializer = AttendanceSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            # 教师权限逻辑:仅同班级教师可打卡
            if user.role == "TEACHER":
                if user.homeroom != serializer.validated_data['user'].room:
                    return Response(
                        {"message": "You don't have permission to perform this action 1"},
                        status=status.HTTP_400_BAD_REQUEST
                    )
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            # 班干部权限逻辑:非学生身份且为班长,仅同班级可打卡
            elif perms is not None:
                if user.role != 'STUDENT' and perms.is_monitor:
                    if user.room != serializer.validated_data['user'].room:
                        return Response(
                            {"message": "You don't have permission to perform this action 2"},
                            status=status.HTTP_400_BAD_REQUEST
                        )
                    serializer.save()
                    return Response(serializer.data, status=status.HTTP_201_CREATED)
            # 无权限兜底
            return Response(
                {"message": "You don't have permission to perform this action 3"},
                status=status.HTTP_400_BAD_REQUEST
            )
        # 序列化验证失败,返回具体错误信息
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

序列化器(Attendance/serializers.py)

from rest_framework import serializers
from .models import Attendance

class AttendanceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Attendance
        fields = ['user', 'Presence', 'leave_reason', 'Date']

    def create(self, validated_data):
        # Date字段由auto_now_add自动填充,无需手动设置
        return Attendance.objects.create(
            user=validated_data['user'],
            Presence=validated_data['Presence'],
            leave_reason=validated_data.get('leave_reason', ''),  # 处理空值场景
            attendance_taker=self.context['request'].user
        )

模型层(可选优化)

Date字段设置auto_now_add=True后,无需null=True,因为会自动填充值:

Date = models.DateField(blank=False, auto_now_add=True)

测试注意事项

  1. Postman请求时,确保user字段传入合法用户ID,Presence仅能传P/A/L三个值
  2. 当Presence为L时,若需强制leave_reason必填,可在序列化器中添加自定义验证
  3. 验证权限逻辑:教师仅能给自己班级的学生打卡,班干部同理

内容的提问来源于stack exchange,提问作者rediet yosef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:10:44