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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:34:53