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)
测试注意事项
- Postman请求时,确保
user字段传入合法用户ID,Presence仅能传P/A/L三个值 - 当
Presence为L时,若需强制leave_reason必填,可在序列化器中添加自定义验证 - 验证权限逻辑:教师仅能给自己班级的学生打卡,班干部同理
内容的提问来源于stack exchange,提问作者rediet yosef
相关产品推荐
相关产品推荐

