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

向Django后端发送POST请求时,userId_id字段出现空值错误

解决Django POST请求中userId_id字段为空的问题

问题原因

你的RunSerializer中将userId和gameId字段设置为read_only=True,并且使用了嵌套的UserSerializer和GameSerializer。这两个配置导致这两个字段仅能用于序列化输出(返回数据给前端),无法接收POST请求传入的输入值,因此后端无法获取到你提交的ID,最终触发外键字段(userId_id、gameId_id)为空的错误。

解决方案

方案一:单序列化器区分读写字段

修改现有序列化器,添加专门用于接收ID的字段,同时保留嵌套字段用于输出:

from rest_framework import serializers
from .models import Run, Game
from django.contrib.auth.models import User

class RunSerializer(serializers.HyperlinkedModelSerializer):
    # 嵌套字段仅用于读取输出
    gameId = GameSerializer(read_only=True)
    userId = UserSerializer(read_only=True)
    
    # 添加用于接收ID的字段,source参数关联到模型的外键字段
    game_id = serializers.PrimaryKeyRelatedField(
        queryset=Game.objects.all(),
        source='gameId'
    )
    user_id = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.all(),
        source='userId'
    )

    class Meta:
        model = Run
        fields = ('id','name','isComplete','deaths','badges','userId','gameId','game_id','user_id')

对应的请求格式

发送POST请求时,使用game_id和user_id传递ID:

{
    "game_id": 1,
    "user_id": 1,
    "name": "testrun2",
    "deaths": 0,
    "badges": 0,
    "isComplete": false
}

方案二:拆分读写序列化器

创建两个序列化器,分别处理数据读取和创建逻辑,视图根据请求方法自动切换:

1. 读取用序列化器(返回数据时使用)

class RunReadSerializer(serializers.HyperlinkedModelSerializer):
    gameId = GameSerializer(read_only=True)
    userId = UserSerializer(read_only=True)

    class Meta:
        model = Run
        fields = ('id','name','isComplete','deaths','badges','userId','gameId')

2. 创建用序列化器(接收POST请求时使用)

class RunCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Run
        fields = ('id','name','isComplete','deaths','badges','gameId','userId')

3. 修改视图类

from rest_framework import generics

class RunList(generics.ListCreateAPIView):
    queryset = Run.objects.all()

    def get_serializer_class(self):
        # POST请求用创建序列化器,其他请求用读取序列化器
        if self.request.method == 'POST':
            return RunCreateSerializer
        return RunReadSerializer

对应的请求格式

直接使用你最初的第一种请求格式即可:

{
    "gameId": 1,
    "userId": 1,
    "name": "testrun2",
    "deaths": 0,
    "badges": 0,
    "isComplete": false
}

原理说明

  • 方案一通过新增game_id和user_id字段,专门接收前端传入的主键ID,source参数将其映射到模型的外键字段gameId和userId,同时保留嵌套字段用于返回格式化后的关联数据。
  • 方案二拆分序列化器后,创建用序列化器直接使用模型的外键字段,DRF会自动验证传入的ID是否存在,并关联到对应的Game和User实例,无需嵌套序列化器处理输入。

内容的提问来源于stack exchange,提问作者Luke Robinson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:51:31