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

Django序列化器报错:期望字典却得到User对象

解决DRF序列化自定义User模型时的"Expected a dictionary, but got User"错误

问题描述

尝试通过API展示自定义User模型字段时,序列化器验证失败,报错:

{"non_field_errors": ["Invalid data. Expected a dictionary, but got User."]}

以下是相关代码:

自定义User模型

from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser, PermissionsMixin


class UserManager(BaseUserManager):
    def _create_user(self, username, password, is_staff, is_superuser, **extra_fields):
        user = self.model(
        username=username,
        is_staff=is_staff,
        is_superuser=is_superuser,
        **extra_fields
    )
    user.set_password(password)
    user.save(using=self.db)
    return user

def create_user(self, username, password=None, **extra_fields):
    return self._create_user(username, password, False, False, **extra_fields)

def create_superuser(self, username, password=None, **extra_fields):
    return self._create_user(username, password, True, True, **extra_fields)


class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=255, unique=True)
    email = models.EmailField( max_length=255, blank=True, null=True)
    name = models.CharField(max_length=255, blank=True, null=True)
    age = models.PositiveIntegerField()
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = []

    def __str__(self):
       return f"{self.id} {self.name} {self.username} {self.age}"

序列化器代码

class UserUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'email', 'username', 'name', 'age']

视图代码

class UserUpdateApiView(APIView):
    def get(self, request, pk):
        try:
            queryset = User.objects.get(pk=pk)
            serializer = UserUpdateSerializer(data=queryset)
            if serializer.is_valid(raise_exception=True):
                return Response(data=serializer.data)
        except User.DoesNotExist:
            return Response(data={"error": "User no found"}, status=status.HTTP_404_NOT_FOUND)

错误原因

核心问题是序列化器初始化传参错误:

  • data参数用于反序列化场景(接收前端传入的字典数据,创建/更新模型实例);
  • 当你要序列化已存在的模型实例(从数据库查询到的User对象),应该直接将实例传入序列化器的instance参数(可省略参数名,直接传第一个位置参数)。

此外,get方法是返回已有数据,不需要调用serializer.is_valid()——该方法仅用于反序列化时验证输入数据,序列化实例时无需验证。

修复方案

1. 修正视图代码

修改视图中序列化器的初始化方式,并移除不必要的验证步骤:

class UserUpdateApiView(APIView):
    def get(self, request, pk):
        try:
            user = User.objects.get(pk=pk)
            serializer = UserUpdateSerializer(user)  # 直接传入实例,无需data参数
            return Response(data=serializer.data)
        except User.DoesNotExist:
            return Response(data={"error": "User not found"}, status=status.HTTP_404_NOT_FOUND)

2. 修正UserManager的缩进错误

原模型中UserManager的_create_user方法存在缩进问题,会导致用户创建逻辑失效,修正后:

class UserManager(BaseUserManager):
    def _create_user(self, username, password, is_staff, is_superuser, **extra_fields):
        user = self.model(
            username=username,
            is_staff=is_staff,
            is_superuser=is_superuser,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)  # 注意这里是self._db,不是self.db
        return user

    def create_user(self, username, password=None, **extra_fields):
        return self._create_user(username, password, False, False, **extra_fields)

    def create_superuser(self, username, password=None, **extra_fields):
        return self._create_user(username, password, True, True, **extra_fields)

内容的提问来源于stack exchange,提问作者Lucin Husein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:15:30