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

访问/profile/报MultipleObjectsReturned错误:get()返回2个CustomUser实例

根因分析

触发MultipleObjectsReturned异常的核心原因有3个,按出现概率从高到低排序:

  1. ProfileView中认证类属性拼写错误,导致JWT认证未生效,认证阶段查询用户逻辑异常
  2. 自定义用户管理器MyUserManager的get_by_natural_key方法实现错误,未按唯一字段phone_number过滤用户
  3. 模型修改后未执行迁移,数据库层面phone_number字段未真正建立主键/唯一约束,存在重复手机号的用户数据

修复步骤

1. 修正ProfileView的错误写法

首先修正认证类属性拼写(单数改复数),同时调整异常捕获的位置到方法内部:

class ProfileView(APIView):
    # 原拼写错误authentication_class,修正为复数
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        try:
            user = model_to_dict(request.user)
            del user['password']
            return Response({"ok": True, "userData": user}, status=200)
        except Exception as e:
            print("::",e,"::")
            return Response({"ok": False, "message": str(e)}, status=500)

2. 修正MyUserManager实现

你自定义了用户管理器,且指定USERNAME_FIELD = 'phone_number',必须保证get_by_natural_key方法按手机号唯一过滤用户,参考正确实现:

from django.contrib.auth.base_user import BaseUserManager

class MyUserManager(BaseUserManager):
    def create_user(self, phone_number, password=None, **extra_fields):
        if not phone_number:
            raise ValueError('手机号为必填项')
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        user = self.model(phone_number=phone_number, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, phone_number, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(phone_number, password, **extra_fields)

    # 该方法是Django认证系统查询用户的核心方法,必须按USERNAME_FIELD过滤
    def get_by_natural_key(self, phone_number):
        return self.get(**{self.model.USERNAME_FIELD: phone_number})

3. 校验数据库约束与数据

先执行以下代码检查是否存在重复手机号的用户:

# 进入Django shell执行
from django.db.models import Count
from yourapp.models import CustomUser # 替换为你自己的app名

# 查询重复手机号
duplicate_phones = CustomUser.objects.values('phone_number').annotate(count=Count('phone_number')).filter(count__gt=1)
print(duplicate_phones)

如果有返回结果,说明数据库存在重复数据:

  • 先手动清理重复的用户记录
  • 重新执行python manage.py makemigrations和python manage.py migrate,确保phone_number的主键、唯一约束在数据库层面生效

4. 注册逻辑优化(可选)

你当前注册逻辑中「判断手机号是否存在」和「创建用户」两步操作存在竞态条件,高并发场景下仍可能插入重复数据,建议直接使用get_or_create或者加数据库事务包裹创建逻辑。


内容的提问来源于stack exchange,提问作者printf-twinkle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:39:02