向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
相关产品推荐
相关产品推荐

