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

Django Rest Framework用户创建异常:后台提示密码格式无效

为什么管理面板会提示「密码格式无效或哈希算法未知」?

咱们先逐个拆解你的三个实现,找出问题所在:

1. views3.py:直接用User.objects.create(**validated_data)——最明显的错误

这个方法会把validated_data里的明文密码直接存入数据库,而Django的认证系统要求密码必须是经过哈希处理的字符串(格式类似pbkdf2_sha256$320000$xxxxxx)。明文密码完全不符合这个规范,所以管理面板必然会报错。

2. views1.py:返回validated_data而非用户实例——违反DRF规范

你的create方法逻辑前半段是对的:创建用户实例、调用set_password()哈希密码、保存到数据库,但最后返回的是validated_data字典,而不是创建好的user_obj实例。

DRF的ModelSerializer要求create方法必须返回创建的模型实例,虽然这个错误不会直接导致密码哈希失效,但会破坏Serializer的正常工作流程,甚至可能在后续操作中引发异常(比如序列化返回数据时出错)。

3. views2.py:逻辑正确,但可能存在隐藏问题

这个实现本身没问题:先通过User(**validated_data)初始化实例,再调用set_password()哈希密码,最后保存。但如果你的自定义User模型对应的UserManager没有正确重写,就可能出问题——因为你把USERNAME_FIELD设为email,还移除了默认的username字段,默认的UserManager是为username设计的,必须重写适配你的自定义模型。

关键修复:重写自定义User模型的Manager

你需要给customuser.User配上正确的UserManager,否则即使调用了set_password,也可能在某些场景下(比如创建超级用户)出现异常。示例代码如下:

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    def create_user(self, email, phone, password=None, **extra_fields):
        if not email:
            raise ValueError('必须设置邮箱字段')
        email = self.normalize_email(email)
        user = self.model(email=email, phone=phone, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, phone, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('超级用户必须设置is_staff=True')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('超级用户必须设置is_superuser=True')

        return self.create_user(email, phone, password, **extra_fields)

然后在你的User模型里关联这个Manager:

class User(AbstractUser):
    # ... 你的字段定义 ...
    objects = UserManager()

推荐的正确Serializer实现

结合上面的分析,优化后的create方法应该是这样的(既严谨又符合DRF规范):

class UserCreateSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['email', 'phone', 'password']
        extra_kwargs = {"password": {"write_only": True}}

    def create(self, validated_data):
        # 先把密码从validated_data中取出,避免直接传给User构造器
        password = validated_data.pop('password')
        user = User(**validated_data)
        user.set_password(password)  # 哈希密码
        user.save()
        return user  # 返回创建好的用户实例

额外修复:settings.py的重复配置

你的settings.py里写了两个REST_FRAMEWORK字典,第二个会完全覆盖第一个,导致你的认证类配置失效。合并成一个字典即可:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]
}

最后一步:清理旧数据

如果你之前用views3创建过用户,数据库里会有明文密码的用户记录,这些记录会一直触发管理面板的报错。你需要删除这些用户,或者通过管理面板重置他们的密码(重置时Django会自动哈希)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:04:04