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

Django REST Framework无法添加对象:user字段类型错误求助

问题分析

错误提示"Incorrect type. Expected pk value, received str."的核心原因是:序列化器处理user外键字段时,默认期望接收用户的主键(即id数值),但你传入的是字符串(比如用户的pseudo),导致验证不通过。同时你的PebblesSerializer的create方法参数错误,它应该接收validated_data而非request。

修复方案

以下提供几种可行的修复方式,优先推荐方案三(利用认证用户自动填充,更安全):

方案一:前端传递用户ID,修正序列化器逻辑

如果需要前端指定用户(不推荐,因为已开启认证),让前端传用户的id值,同时修正序列化器的create方法:

class PebblesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pebbles
        fields = ["id","image","user"]

    # 修正create方法参数为validated_data
    def create(self, validated_data):
        return Pebbles.objects.create(**validated_data)

此时前端请求体示例:

{
    "image": "xxx.jpg",
    "user": 1  // 这里填用户的id数值
}

方案二:自定义外键字段,支持通过pseudo关联用户

如果需要前端传用户的pseudo而非id,可以自定义外键字段,让序列化器自动根据pseudo查询用户:

class PebblesSerializer(serializers.ModelSerializer):
    # 自定义user字段,指定用pseudo匹配用户
    user = serializers.SlugRelatedField(
        slug_field='pseudo',
        queryset=UserData.objects.all()
    )

    class Meta:
        model = Pebbles
        fields = ["id","image","user"]

    def create(self, validated_data):
        return Pebbles.objects.create(**validated_data)

此时前端请求体示例:

{
    "image": "xxx.jpg",
    "user": "test_pseudo"  // 填用户的pseudo字符串
}

方案三:利用认证用户自动填充(推荐)

视图已经配置了IsAuthenticated权限,说明当前请求的用户已经登录,完全可以直接用request.user填充Pebbles的user字段,无需前端传递,既安全又避免错误:

方式1:重写视图的perform_create方法

修改PebblesView,去掉自定义的create方法,改用框架推荐的perform_create:

class PebblesView(generics.ListCreateAPIView):
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]
    serializer_class = PebblesSerializer
    queryset = Pebbles.objects.all()  # 直接定义查询集,无需重写get_queryset

    # 重写该方法,自动传递当前登录用户
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

同时修改PebblesSerializer,设置user为只读字段,避免前端传递:

class PebblesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pebbles
        fields = ["id","image","user"]
        read_only_fields = ["user"]  # 标记为只读,前端无需传该字段

此时前端请求体只需传:

{
    "image": "xxx.jpg"
}

方式2:在序列化器的create方法中获取当前用户

也可以通过序列化器的context拿到请求对象,进而获取当前用户:

class PebblesSerializer(serializers.ModelSerializer):
    class Meta:
        model = Pebbles
        fields = ["id","image","user"]
        read_only_fields = ["user"]

    def create(self, validated_data):
        # 从context中取出request,拿到当前登录用户
        user = self.context['request'].user
        return Pebbles.objects.create(user=user, **validated_data)

这种方式下视图无需额外修改,框架会自动调用序列化器的create方法。

额外说明

你在Django Shell中能创建成功,是因为直接通过UserData.objects.get(pseudo=xxx)拿到了用户对象;但序列化器默认的外键字段只接受主键值,所以前端传字符串会触发验证错误。优先用方案三,既符合认证逻辑,又能避免前端传参错误。

内容的提问来源于stack exchange,提问作者Alves Gustavo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:10:55