Django视图执行异常:Team Leader创建早于User创建完成
问题分析与解决方案
问题原因
你的解读完全正确:fetch 是异步操作,两个POST请求会并行发送,导致创建Team Leader的请求在User创建完成前就执行,此时数据库中还没有对应的User记录,因此触发 User.DoesNotExist 错误。
修复方案
前端:确保请求顺序执行
修改JavaScript代码,让第二个请求等待第一个请求完成后再发送,推荐使用async/await语法,代码更清晰易读:
async function submitRegistration() { let userUrl = homeUrl + 'api/createuser/' try { // 先发送创建User的请求,等待执行完成 const userResponse = await fetch(userUrl,{ method:'POST', headers:{ 'Content-type':'application/json', 'X-CSRFToken':csrftoken, }, body:JSON.stringify({ "username": username, "first_name": firstname, "last_name": lastname, "email": email, "password": password1, "employeeRole": employeeRole, "teamLeader": teamLeader, }), }) // 检查User创建是否成功 if (!userResponse.ok) { throw new Error('用户创建失败'); } // 再发送创建Team Leader/Member的请求 let regisUrl; if (employeeRole == 'Member') { regisUrl = homeUrl + 'api/createMember/'; } else { regisUrl = homeUrl + 'api/createTeamLeader/'; } const roleResponse = await fetch(regisUrl,{ method:'POST', headers:{ 'Content-type':'application/json', 'X-CSRFToken':csrftoken, }, body:JSON.stringify({ "username": username, "first_name": firstname, "last_name": lastname, "email": email, "password": password1, "employeeRole": employeeRole, "teamLeader": teamLeader, }), }) if (!roleResponse.ok) { throw new Error('角色创建失败'); } // 注册成功后的逻辑,比如跳转页面或提示用户 console.log('注册完成'); } catch (error) { console.error('注册出错:', error); // 这里可以添加前端错误提示逻辑 } } // 调用函数提交注册 submitRegistration();
后端:优化接口逻辑(可选但推荐)
1. 合并创建接口
直接在createUser接口中根据employeeRole自动创建对应的Team Leader/Member,避免两次请求,同时保证数据一致性:
from rest_framework import status @api_view(['POST']) def createUser(request): serializerUser = UserSerializer(data=request.data) if serializerUser.is_valid(): username = serializerUser.validated_data['username'] password = serializerUser.validated_data['password'] email = serializerUser.validated_data['email'] employeeRole = request.data.get('employeeRole') # 创建User user = User.objects.create_user(username, email, password) user.first_name = serializerUser.validated_data['first_name'] user.last_name = serializerUser.validated_data['last_name'] user.save() # 根据角色自动创建关联对象 if employeeRole == 'Team Leader': TeamLeader.objects.create( user=user, firstName=user.first_name, lastName=user.last_name, email=email, username=username, employeeRole=employeeRole ) elif employeeRole == 'Member': # 替换为Member模型的创建逻辑 Member.objects.create( user=user, # 填充Member模型所需字段 ) print('用户与角色创建成功') return Response(serializerUser.data, status=status.HTTP_201_CREATED) return Response(serializerUser.errors, status=status.HTTP_400_BAD_REQUEST)
2. 优化模型与序列化器
- 移除
TeamLeader模型中冗余字段:firstName、lastName、email、username这些字段已经在User模型中存在,无需重复存储,直接通过user外键关联查询即可。 - 编写嵌套序列化器,简化参数传递:
# 序列化器示例 class TeamLeaderSerializer(serializers.ModelSerializer): user = UserSerializer(read_only=True) user_id = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), write_only=True) class Meta: model = TeamLeader fields = ['user_id', 'user', 'employeeRole', 'bio', 'profileimg', 'location']
3. 增加错误处理
在createTeamLeader接口中捕获User.DoesNotExist异常,返回友好的错误响应:
from django.core.exceptions import ObjectDoesNotExist from rest_framework import status @api_view(['POST']) def createTeamLeader(request): serializer = TeamLeaderSerializer(data=request.data) if serializer.is_valid(): username = serializer.validated_data['username'] try: newAddedUser = User.objects.get(username=username) except ObjectDoesNotExist: return Response({"error": "目标用户不存在"}, status=status.HTTP_404_NOT_FOUND) teamleader = TeamLeader.objects.create( user=newAddedUser, firstName=newAddedUser.first_name, lastName=newAddedUser.last_name, email=serializer.validated_data['email'], username=username, employeeRole=serializer.validated_data['employeeRole'] ) return Response(TeamLeaderSerializer(teamleader).data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
4. 使用事务保证数据一致性
如果保留两个独立接口,在创建User和关联角色时使用数据库事务,确保操作要么全部成功,要么全部回滚:
from django.db import transaction from rest_framework import status @api_view(['POST']) def createUser(request): try: with transaction.atomic(): serializerUser = UserSerializer(data=request.data) if serializerUser.is_valid(): # 创建User逻辑... user.save() # 可选:直接创建关联角色... return Response(serializerUser.data) return Response(serializerUser.errors) except Exception as e: return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
内容的提问来源于stack exchange,提问作者Kevin Melendres
相关产品推荐
相关产品推荐

